Problème de ClassLoader

Problème de ClassLoader - Java - Programmation

Marsh Posté le 26-03-2004 à 16:43:52    

Salut les gens !
 
J'ai un petit prob avec un class loader artisanal... Quand je lance le programme ci-dessous, le class loader dit qu'il peut instancier la classe (j'ai même mis un log dans le constructeur)... par contre, sitôt que j'essaie d'utiliser l'objet créé... paf NoClassDefFoundError
 
Valà le prog main :

Code :
  1. public static void main (String args[])
  2.     {
  3. TestCustomURLClassLoader tcl = new    TestURLClassLoader();
  4. CustomURLClassLoader customCL = new CustomURLClassLoader();
  5. try {
  6.     Class dummy = customCL.loadClass("javasec.classload.DummyClass", true);
  7.     System.out.println ("Class dummyCL : " + dummy.getName());
  8.     System.out.println ("dummy: class loader : " + dummy.getClassLoader().toString());
  9.     Object object = dummy.newInstance();
  10.           // l'erreur apparait seulement si je met cette ligne...
  11.     System.out.println("Dummy object value : " + ((DummyClass)object).getValue());
  12. } catch (Exception e1) {
  13.     e1.printStackTrace();
  14. }
  15.     }
  16. }


 
Alors si qqun à une idée qu'il veut absolument me faire partager, surtout pas de gêne entre nous  :)  
 
Ah encore une remarque... bien entendu, la classe DummyClass n'est pas dans le classpath, sinon elle n'est pas chargé par mon class loader, mais par le class loader de base... et c'est nettement moins intéressant...
 
Je ne sais si l'output de ce programme à de l'intérêt, mais au cas ou :

Code :
  1. CustomURLClassLoader constructor
  2. url[0] : http://localhost:8000/
  3. url[1] : file:/home/azubi/AJClasses/
  4. CustomURLClassLoader::loadClass() javasec.classload.DummyClass
  5. CustomURLClassLoader::findClass()javasec.classload.DummyClass
  6. CustomURLClassLoader::getPermissions()
  7. CustomURLClassLoader::loadClass() java.lang.Object
  8. Class dummyCL : javasec.classload.DummyClass
  9. Exception in thread "main" java.lang.NoClassDefFoundError: javasec/classload/DummyClass
  10. dummy: class loader : javasec.classload.CustomURLClassLoader@1034bb5
  11. CustomURLClassLoader::loadClass() java.lang.System
  12.         at javasec.classload.TestCustomURLClassLoader.main(Unknown Source)
  13. CustomURLClassLoader::loadClass() java.io.PrintStream
  14. DummyClass::constructor...
  15. CustomURLClassLoader::loadClass() java.lang.StringBuffer
  16. DummyClass::constructor ok!7
  17. Java Result: 1


Message édité par leonhard le 26-03-2004 à 16:50:43
Reply

Marsh Posté le 26-03-2004 à 16:43:52   

Reply

Marsh Posté le 26-03-2004 à 17:13:01    


A vue de nez c'est un probleme de relations entre classLoaders. Il faut savoir qu'en Java, une classe est associee a un classLoader qui definit un espace de nom. Par exemple, tu peux avoir 2 classes Toto dans la meme VM, une chargee par un CL (disons A) et une autre par un CL B. Du point de vue de la VM, ce seront 2 classes differentes. Pour remedier a ca, il y a la notion de classLoader parent.  
 
Ton probleme est probablement  celui la. Plus exactement, la classe Dummy a ete chargee par customCL. Mais la classe de ton programme a ete chargee par le CL "standard" (SecureClassLoader). Or si ton customCL n'a pas ete construit comme fils du CL standard ET n'a pas demande au CL standard de charger lui aussi la classe Dummy, tu ne peux pas les voir.  
 
Un petit schema pour expliquer (le premier class loader est le CL primordial, tu n'y a pas acces, c'est celui qui chargent les classes java de base et qui charge les autres CLs)
 
         CL Primordial
         /
        /
    SecureClassLoader
       |
       |
    URLClassLoader  
       |
       |
    CustomURLClassLoader
 
Tu dois avoir cette situation si tu veux que ca marche, mais ce n'est pas suffisant. Il faut que lorsque ton CustomURLClassLoader charge la classe, il demande a son parent de la charger pour lui.  
 
Y'a pas de solution miracle, ca depend vraiment de ce que tu veux faire. Pour t'aider a debugger, tu peux demander a voir le CL utilise pour charger une classe:
 
 

Code :
  1. System.out.println(object.getClass().getClassLoader());


 
Ca te permettra de voir qui charge quoi.
 
Pour te donner un exemple, dans le Java de Sun, l'URLClassLoader ne charge pas de classe, il ne fait que trouver ou elle se trouve. Ensuite, il appelle loadClass de son parent, le SecureClassLoader.
 
Looz

Reply

Marsh Posté le 26-03-2004 à 17:19:59    

loozerz a écrit :


...
Ton probleme est probablement  celui la. Plus exactement, la classe Dummy a ete chargee par customCL. Mais la classe de ton programme a ete chargee par le CL "standard" (SecureClassLoader). Or si ton customCL n'a pas ete construit comme fils du CL standard ET n'a pas demande au CL standard de charger lui aussi la classe Dummy, tu ne peux pas les voir.  
 
...
 


 
ben justement ma classe Dummy est bien chargée par mon class loader.. mais je vais encore lire attentivement ce que tu as écrit pour essayer de comprendre ou j'ai merdé... Parce que je voudrais vraiment que ma classe soit chargée par mon class loader et pas par le class loader qui charge les classes du classpath et qui a donc chargé mon programm main...
 
merci de ton aide

Reply

Marsh Posté le 26-03-2004 à 17:47:05    

Si tu fais charger ta class dummy uniquement par ton CL, les classes chargees par d'autres CL ne la verront pas. C'est une securite de Java.  
 
Looz.

Reply

Marsh Posté le 26-03-2004 à 20:31:26    

ben déjà je suis étonné que ton programme s'execute jusque là vu que tu as une référence en dur dans la classe main à la classe "DummyClass" (dans le cast) => au chargement de la calsse main, le classloader system va essayer de charger la DummyClass et donc ca devrait planter puisque tu précises qu'elle n'est pas accessible dans le classpath

Reply

Marsh Posté le 26-03-2004 à 21:01:03    

benou a écrit :

ben déjà je suis étonné que ton programme s'execute jusque là vu que tu as une référence en dur dans la classe main à la classe "DummyClass" (dans le cast) => au chargement de la calsse main, le classloader system va essayer de charger la DummyClass et donc ca devrait planter puisque tu précises qu'elle n'est pas accessible dans le classpath


 
ben mon class loader perso est une sous-classe de URLClassLoader. Donc en donnant le bon url au constructeur du class loader, il la trouve... En plus en mettant des traces diverses, je vois :
1) mon class loader essaye de déléguer le chargement de la classe DummyClass à son parent... et comme ça ne marche pas, il la charge lui-même...
 
2)Le class loader parent de mon class loader est le class loader qui a chargé le programme main (Launcher$AppClassLoader@92e78c) même classe, même instance...
 
3) si je crée l'instance de DummyClass avec un newInstance(), il crée bien l'objet (le constructeur no-args est bien appellé sans erreur), mais ensuite y'a NoClassDefFoundError si j'essaie d'accéder à une méthode ou à un argument de cet objet...  
 
Je pensais que c'était un problème de codebase ou qq chose comme ça (genre annotation de la classe), mais je n'ai encore rien trouvé... je ne désespère pas d'y arriver cependant.
 
merci pour votre aide et bonne soirée

Reply

Marsh Posté le 26-03-2004 à 22:09:39    

t'as pas répondu à mon intérogation ... tu trouves pas bizarre de faire une référence statique à une classe sensée ne pas être disponible par le classloader par défaut ??
 
Essaye de faire la même chose en invoquant la méthode getValue dynamiquement...

Reply

Marsh Posté le 26-03-2004 à 22:41:20    

benou a écrit :

t'as pas répondu à mon intérogation ... tu trouves pas bizarre de faire une référence statique à une classe sensée ne pas être disponible par le classloader par défaut ??
 
Essaye de faire la même chose en invoquant la méthode getValue dynamiquement...


 
t'as raison, mais je ne comprends pas très bien ce que tu entends par "appeller la méthode getValue() dynamiquement". Est-ce que je dois utiliser l'introspection pour appeller cette méthode par un invoke ? autrement je vois pas trop comment faire... comment caster un la variable Object en DummyClass sans le faire statiquement ... désolé, je suis un petit peu lent à la détente

Reply

Marsh Posté le 26-03-2004 à 22:54:14    

leonhard a écrit :


Est-ce que je dois utiliser l'introspection pour appeller cette méthode par un invoke ?  


c'est ca :jap:
 

leonhard a écrit :


comment caster un la variable Object en DummyClass sans le faire statiquement ...


ca tu peux pas ... A la rigueur, tu peux passer par une interface qui est dans le classpath et que l'objet que tu créés dynamiquement implémente...
 
mais bon, de toute façon je ne suis  pas sûr que ton problème vienne de là ... En fait, je m'attendrais à ce que ton programme plante dès le lancement parce qu'il me semble que toute les classes utilisées (statiquement) à l'intérieur d'une classe sont chargées lors du premier chargement de cette classe.
 

Reply

Marsh Posté le 26-03-2004 à 23:46:06    

benou a écrit :


plein de choses intéressantes...


 
mais pour le moment ça marche pô... mais bon à cette heure, je commence à avoir des tdc à la place des yeux, alors merci pour ton aide et à charge de revanche (ben quoi, on peut rêver non ?)

Reply

Marsh Posté le 26-03-2004 à 23:46:06   

Reply

Marsh Posté le 27-03-2004 à 15:32:58    

leonhard a écrit :


 
mais pour le moment ça marche pô... mais bon à cette heure, je commence à avoir des tdc à la place des yeux, alors merci pour ton aide et à charge de revanche (ben quoi, on peut rêver non ?)


 
ben si ça marche... faut juste écouter les conseils de Môssieur Benou et pas écrire n'importe quoi...  
 
merci donc Môssieur Benou!

Reply

Marsh Posté le 28-03-2004 à 03:51:53    

leonhard a écrit :


 
ben si ça marche... faut juste écouter les conseils de Môssieur Benou et pas écrire n'importe quoi...  
 
merci donc Môssieur Benou!


de rien :)
 
c'est avec l'invocation dynamique que ca marche c'est ca ?

Reply

Marsh Posté le 28-03-2004 à 12:30:08    

benou a écrit :


de rien :)
 
c'est avec l'invocation dynamique que ca marche c'est ca ?


 
Yep !

Reply

Marsh Posté le 23-02-2013 à 14:47:00    

je veux utiliser un jar externe à mon application et j'utilise un classloader mais je n'arrive pas à instancier la class de mon application qui utilise des packages externe dans ce jar.Merci pour votre aide

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed