2011-10-19 18 views
5

Tengo un archivo jar con 30 clases de más o menos. Lo que quiero es que al comienzo del método principal invoque una clase desde este contenedor que, utilizando las capacidades de reflexión de Java, obtiene Class referencias a cada clase en el contenedor. Mi objetivo final es realizar algún tipo de operación, consultar una variable que se define para cada clase. Básicamente estoy buscando algo así como. ¿Hay alguna manera fácil de hacerlo utilizando las API estándar de reflexión o será una gran molestia crear una solución funcional?¿Cómo puedo obtener el objeto de clase para cada clase en un jar

List l = Reflection.getAllClasses(); 
String var; 
foreach(Class c : l) { 
    var = c.getField("fieldname"); 
    doSomething(var); 
} 

Editar:

Sólo para que quede claro: El código se ejecuta desde el frasco withing inspeccionado.

+0

¿Por qué no incluir una lista (por ejemplo, utilizando un archivo 'Properties') de clases en el archivo Jar cuando se hace? +1 para indicar el objetivo final. –

+0

@AndrewThompson porque no quiero soportar esta carga de gestión, siempre recordando la lista de archivos. – LordDoskias

+0

Sería trivial escribir una clase que prepare la lista como parte del proceso de compilación. Sin carga en absoluto. –

Respuesta

6

Esto hace el truco para mí:

import java.io.IOException; 
import java.util.ArrayList; 
import java.util.Collection; 
import java.util.Enumeration; 
import java.util.jar.JarEntry; 
import java.util.jar.JarFile; 


public class ClassFinder 
{ 
    public static void main(String[] args) throws IOException 
    { 
    Collection<Class<?>> classes = new ArrayList<Class<?>>(); 

    JarFile jar = new JarFile("/home/nono/yamts/yamts.jar"); 
    for (Enumeration<JarEntry> entries = jar.entries() ; entries.hasMoreElements() ;) 
    { 
     JarEntry entry = entries.nextElement(); 
     String file = entry.getName(); 
     if (file.endsWith(".class")) 
     { 
      String classname = file.replace('/', '.').substring(0, file.length() - 6); 
      try 
      { 
       Class<?> c = Class.forName(classname); 
       classes.add(c); 
      } 
      catch (Throwable e) 
      { 
       System.out.println("WARNING: failed to instantiate " + classname + " from " + file); 
      } 
     } 
    } 

    for (Class<?> c : classes) 
     System.out.println(c); 
    } 
} 
+0

pero esto funcionará para un archivo jar externo. ¿Qué ocurre si el código mencionado anteriormente se va a ejecutar con el mismo contenedor que el objetivo? Editar: También tu código no funciona para mí. Para cada clase, "fallé al crear instancias" – LordDoskias

+0

. Siempre que el contenedor esté en el classpath, puede recuperar la definición de clase. Si el contenedor especificado no se encuentra en la ruta de clase, entonces es probable que deba invertir trabajo adicional para un cargador de clases personalizado. – dagnelies

+0

Funcionó a la perfección, muchas gracias – LordDoskias

1

Listar todas las clases en un archivo JAR no es algo que se pueda hacer con la reflexión.

Sin embargo, se puede hacer utilizando un JarInputStream.

+0

Y también sin JarInputStream, mediante el uso de JarFile (como lo demuestra la respuesta aceptada) :) – Grodriguez

0

La siguiente solución funcionará con una jar que está en su classpath o fuera de su classpath.

try { 
     File pathToJar = new File("C:/some.jar"); 

     JarFile jarFile; 
      jarFile = new JarFile(pathToJar); 
     Enumeration<JarEntry> e = jarFile.entries(); 

     URL[] urls = { new URL("jar:file:" + pathToJar+"!/") }; 
     URLClassLoader cl = URLClassLoader.newInstance(urls); 

     while (e.hasMoreElements()) { 
      JarEntry je = e.nextElement(); 
      if(je.isDirectory() || !je.getName().endsWith(".class")){ 
       continue; 
      } 
      // -6 because of .class 
      String className = je.getName().substring(0,je.getName().length()-6); 
      className = className.replace('/', '.'); 
      System.out.println("Checking for class " + className); 
      Class c = cl.loadClass(className); 


      System.out.println("Class object " + c.getName()); 

     } 
    } catch (IOException | ClassNotFoundException e1) { 
     // TODO Auto-generated catch block 
     e1.printStackTrace(); 
    } 
Cuestiones relacionadas