web-dev-qa-db-fra.com

Comment utiliser URLClassLoader pour charger un fichier * .class?

Je joue avec Reflection et je pensais créer quelque chose qui chargerait une classe et afficherait le nom de tous les champs de la classe ..__ J'ai créé une petite classe de type hello world pour pouvoir inspecter:

kent@rat:~/eclipsews/SmallExample/bin$ ls
IndependentClass.class
kent@rat:~/eclipsews/SmallExample/bin$ Java IndependentClass 
Hello! Goodbye!
kent@rat:~/eclipsews/SmallExample/bin$ pwd
/home/kent/eclipsews/SmallExample/bin
kent@rat:~/eclipsews/SmallExample/bin$ 

Sur la base de ce qui précède, je tire deux conclusions:

  • Il existe dans /home/kent/eclipsews/SmallExample/bin/IndependentClass.class
  • Ça marche! (Il doit donc s'agir d'un fichier .class approprié pouvant être chargé par un chargeur de classe)

Ensuite, le code qui doit utiliser Reflection: (La ligne qui provoque une exception est marquée)

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());
        }
    }
}

Mais quand je le lance, je reçois:

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)

Mes questions:

  1. Qu'est-ce que je fais mal ci-dessus? Comment je le répare?
  2. Est-il possible de charger plusieurs fichiers de classe et de les parcourir par la suite?
29
user14070

Depuis les Javadocs du constructeur URLClassLoader(URL[]) :

Construit un nouveau URLClassLoader pour les URL spécifiées à l'aide du ClassLoader parent de délégation par défaut. Les URL seront recherchées dans l'ordre spécifié pour les classes et les ressources après la première recherche dans le chargeur de classes parent. Toute URL se terminant par un '/' est supposée faire référence à un répertoire. Sinon, l'URL est supposée faire référence à un fichier JAR qui sera téléchargé et ouvert selon les besoins. 

Donc, vous avez deux options:

  1. Reportez-vous au répertoire dans lequel se trouve le fichier .class.
  2. Placez le fichier .class dans un fichier JAR et reportez-vous à celui-ci.

(1) est plus facile dans ce cas, mais (2) peut être pratique si vous utilisez des ressources en réseau.

38
Michael Myers

Vous devez fournir les répertoires ou les fichiers JAR contenant vos fichiers .class à URLClassLoader:

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

Et oui, vous pouvez charger autant de classes que vous le souhaitez

10
Maurice Perry

Vous devez charger la classe en donnant le nom de classe complet qui est le nom de classe avec son chemin de package comme

Class c = ucl.loadClass("com.mypackage.IndependentClass");
6
Suresh

J'avais un problème similaire mais mon fichier de classe résidait dans un paquet nommé "customElements". Dans de tels scénarios, l'URL doit être construite jusqu'au dossier situé juste au-dessus du package racine et dans la méthode de chargement, le nom complet de la classe, package compris, doit être transmis. Par exemple, dans mon cas; L'URL était comme:

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();
}

Et le chargement réel était comme:

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

Où childFirstClassLoader est mon chargeur de classe.

0
CoolCoder