2009-04-10 18 views
27

Juego con Reflection y pensé en hacer algo que cargue una clase e imprima los nombres de todos los campos de la clase. he hecho un pequeño hola mundo tipo de distinción a tener algo para inspeccionar:Cómo usar URLClassLoader para cargar un archivo * .class?

[email protected]:~/eclipsews/SmallExample/bin$ ls 
IndependentClass.class 
[email protected]:~/eclipsews/SmallExample/bin$ java IndependentClass 
Hello! Goodbye! 
[email protected]:~/eclipsews/SmallExample/bin$ pwd 
/home/kent/eclipsews/SmallExample/bin 
[email protected]:~/eclipsews/SmallExample/bin$ 

base en lo anterior saco dos conclusiones:

  • Existe en/home/Kent/eclipsews/SmallExample/bin/IndependentClass.class
  • ¡Funciona! (Por lo tanto, debe ser un .class-archivo adecuado que puede ser cargado por un cargador de clases)

continuación, el código que se va a utilizar la reflexión: (Línea que provoca una excepción está marcado)

import java.lang.reflect.Field; 
import java.net.MalformedURLException; 
import java.net.URL; 
import java.net.URLClassLoader; 

public class InspectClass { 
    @SuppressWarnings("unchecked") 
    public static void main(String[] args) throws ClassNotFoundException, MalformedURLException { 
     URL classUrl; 
     classUrl = new URL("file:///home/kent/eclipsews/SmallExample/bin/IndependentClass.class"); 
     URL[] classUrls = { classUrl }; 
     URLClassLoader ucl = new URLClassLoader(classUrls); 
     Class c = ucl.loadClass("IndependentClass"); // LINE 14 
     for(Field f: c.getDeclaredFields()) { 
      System.out.println("Field name" + f.getName()); 
     } 
    } 
} 

Pero cuando lo ejecuto me sale:

Exception in thread "main" java.lang.ClassNotFoundException: IndependentClass 
    at java.net.URLClassLoader$1.run(URLClassLoader.java:200) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at java.net.URLClassLoader.findClass(URLClassLoader.java:188) 
    at java.lang.ClassLoader.loadClass(ClassLoader.java:306) 
    at java.lang.ClassLoader.loadClass(ClassLoader.java:251) 
    at InspectClass.main(InspectClass.java:14) 

Mis preguntas:

  1. ¿Qué estoy haciendo mal ¿encima? ¿Cómo lo arreglo?
  2. ¿Hay alguna forma de cargar varios archivos de clase e iterar sobre ellos?
+0

advertencias Qué estás suprimiendo? –

+1

Un error común es usar el directorio actual como URL, pero también usar el directorio actual para sus clases normales. Debido a que el elemento primario predeterminado es el cargador de clases del sistema, su cargador de clases no tiene la oportunidad de cargar la clase. –

+0

archivo: ///home/kent/eclipsews/SmallExample/bins/IndependentClass.class que debe ser: archivo: ///home/kent/eclipsews/SmallExample/bin/IndependentClass.class? – dfa

Respuesta

34

Desde el Javadocs for the URLClassLoader(URL[]) constructor :

Crea un nuevo URLClassLoader para las URL especificadas utilizando la delegación primaria principal ClassLoader. Las URL se buscarán en el orden especificado para las clases y recursos después de la primera búsqueda en el cargador de clases padre. Se supone que cualquier URL que termine con un '/' hace referencia a un directorio. De lo contrario, se supone que la URL hace referencia a un archivo JAR que se descargará y abrirá según sea necesario.

lo que tiene dos opciones:

  1. referirse al directorio que el archivo .class está en
  2. poner el archivo .class en un frasco y se refieren a que

(1) es más fácil en este caso, pero (2) puede ser útil si está utilizando recursos de red.

+0

+1 ¡Gracias! Estas son las cosas en las que uno nunca piensa. – Daniel

9

Debe proporcionar los directorios o los archivos JAR que contiene los archivos .class a la URLClassLoader:

classUrl = new URL("file:///home/kent/eclipsews/SmallExample/bin/"); 

Y sí, puede cargar tantas clases como desee

1

Estaba teniendo un problema similar pero mi archivo de clase residía dentro de un paquete llamado "elementos personalizados". En tales escenarios, la URL debe construirse hasta la carpeta justo arriba del paquete raíz y en el método de carga se debe pasar el nombre completo de la clase, incluido el paquete.Por ejemplo, en mi caso; Era como URL:

File customElementsDir = new File("D:/My Space"); 
//File customElementsDir = new File("D:\\customElements"); 
URL[] urls = null; 
try { 
    URL url = customElementsDir.toURI().toURL(); 
    urls = new URL[] { url }; 
} catch (MalformedURLException e) { 
    // TODO Auto-generated catch block 
    e.printStackTrace(); 
} 

Y carga real era como:

clazz = childFirstClassLoader 
      .loadClass("customElements.CustomLoadableClass"); 

Dónde childFirstClassLoader es mi cargador de clases.

6

Hay que cargar la clase dando el nombre completo de la clase que es el nombre de la clase con con la ruta de paquete como,

Class c = ucl.loadClass("com.mypackage.IndependentClass"); 
Cuestiones relacionadas