2009-04-10 6 views
27

Je suis en train de jouer avec Reflection et j'ai pensé faire quelque chose qui charge une classe et imprime les noms de tous les champs de la classe. J'ai fait un type de monde petit bonjour de classe pour avoir quelque chose à vérifier:Comment utiliser URLClassLoader pour charger un fichier * .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$ 

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

  • Il existe dans/home/kent/eclipsews/SmallExample/bin/IndependentClass.class
  • Cela fonctionne! (Il doit donc être un bon .class fichier qui peut être chargé par un chargeur de classe)

Ensuite, le code qui est d'utiliser la réflexion: (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 au dessus? Comment je le répare?
  2. Existe-t-il un moyen de charger plusieurs fichiers de classe et de les parcourir par-dessus?
+0

Que vous? La suppression de mises en garde –

+1

Une erreur courante consiste à utiliser le répertoire courant comme URL, mais aussi à utiliser le répertoire courant pour vos classes normales. Comme le parent par défaut est le chargeur de classe système, votre chargeur de classe n'a pas la possibilité de charger la classe. fichier –

+0

: ///home/kent/eclipsews/SmallExample/bins/IndependentClass.class il devrait être: fichier: ///home/kent/eclipsews/SmallExample/bin/IndependentClass.class? – dfa

Répondre

34

De l'Javadocs for the URLClassLoader(URL[]) constructor :

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

Alors vous avez deux options:

  1. Référez-vous au répertoire que le fichier .class est
  2. Mettre le fichier .class dans un JAR et se réfèrent à cette

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

+0

+1 Merci! Ce sont les choses auxquelles on ne pense jamais. – Daniel

9

Vous devez fournir les répertoires ou les fichiers jar contenant vos fichiers .class au URLClassLoader:

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

Et oui, vous pouvez charger autant de classes que vous aimez

1

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 juste au-dessus du paquet de racine et dans la méthode de chargement le nom complet de la classe comprenant le paquet devrait être passé.Par exemple, dans mon cas; 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 chargement réel était comme:

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

Où est ma childFirstClassLoader classloader.

6

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

Class c = ucl.loadClass("com.mypackage.IndependentClass"); 
Questions connexes