Erreur de cast en chargeant jar dynamiquement

Erreur de cast en chargeant jar dynamiquement - Java - Programmation

Marsh Posté le 15-03-2010 à 19:57:20    

Bonjour à tous,
 
Je me tourne vers vous car je m'arrache quelque peu les cheveux :fou:
 
Tout d'abord, je dispose d'une interface iRequeteMoodle (public interface iRequeteMoodle), une classe abstraite AbstractRequeteBarChart (public abstract class AbstractRequeteBarChart implements iRequeteMoodle) et de deux classes RequeteBarChartEnFonctionModule (public class RequeteBarChartEnFonctionModule extends AbstractRequeteBarChart) et RequeteBarChartEnFonctionTemps (public class RequeteBarChartEnFonctionTemps extends AbstractRequeteBarChart).
 
Lorsque je demande à caster un objet AbstractRequeteBarChart dans un iRequeteMoodle en dur dans le code, pas de souci.

Code :
  1. package tests;
  2. import moodle.requete.RequeteBarChartEnFonctionModule;
  3. import moodle.requete.iRequeteMoodle;
  4. public class TestRequete {
  5. public static void main(String[] args) {
  6.  iRequeteMoodle iRM = new RequeteBarChartEnFonctionModule();
  7.  System.out.println(iRM);
  8. }
  9. }


Le code ci dessus marche nickel.
 
Par contre, quand je charge des classes contenues dans des fichiers jar de manière dynamique (en passant par des ((Class)tmpClass).newInstance ();, ou tmpClass est, par exemple, un RequeteBarChartEnFonctionModule) et que je les caste dans la foulée, j'ai un magnifique java.lang.ClassCastException: moodle.requete.RequeteBarChartEnFonctionModule cannot be cast to moodle.requete.iRequeteMoodle, ce qui est très gênant... Si j'essai de stocker mon instance dans un tableau d'objets, j'ai l'exception java.lang.ArrayStoreException qui est levée.
 
Comment peut-on caster une instance d'objet chargée dans un jar (j'ai essayé de mettre dans le jar toutes les classes utilisées, et j'ai toujours ce souci) ?
 
Merci d'avance :jap:

Reply

Marsh Posté le 15-03-2010 à 19:57:20   

Reply

Marsh Posté le 16-03-2010 à 17:26:09    

C'est un problème de ClassLoader. Si tu as la même classe chargée par 2 ClassLoaders différents, elles seront considérées comme différentes par la JVM, et il sera donc impossible de faire un cast d'une vers l'autre.
 
Pour ton problème, je dirais que le problème est certainement que tu ne charges pas les classes de ton jar avec un descendant du classloader qui a été utilisé pour le reste du code.
 
Comment est-ce que tu charges ton jar ? Avec un URLClassLoader ? Tu précises le parent ou pas ?

Reply

Marsh Posté le 16-03-2010 à 18:13:14    

En effet j'utilise un URLClassLoader, qui contient l'url du répertoire et de mes fichiers jar. Je regarde juste si le fichier courant dans le jar n'est ni une interface, ni une classe abstraite, et j'instancie systématiquement. Je dois en effet utiliser la même classe dans 2 jars différents, qui sont aussi chargés selon les besoins (donc possibilité d'utilisation concourante).
 
Je vais essayer d'en supprimer une dans un jar, voir si ce problème de cast continue :)
 
Merci pour l'aide !

Reply

Marsh Posté le 17-03-2010 à 11:32:38    

Quand tu construis ton URLClassLoader, tu lui donnes un parent ou pas ? Parce que c'est certainement là que ce trouve le problème.
 
Si tu lui donnes en parent le classloader de la classe courante, ça pourrait aider à résoudre le problème. Tu peux l'obtenir avec this.getClass().getClassLoader()
 
Quand tu donnes un parent à ton URLClassLoader, Java commencera par chercher ses classes dans celui-ci. Ça évite donc d'avoir une même classe chargée 2 fois, et ainsi les soucis de ClassCastException.

Reply

Marsh Posté le 17-03-2010 à 14:29:22    

Quand je construis mon URLClassLoader, je lui fournit un tableau d'URL relatifs à mes fichiers jars. Rien en rapport avec le classloader déjà existant.
 

Code :
  1. URL u = null;
  2. try {
  3. u = f.toURI().toURL();
  4. } catch (MalformedURLException e) {
  5. e.printStackTrace();
  6. }
  7. ClassLoader jarClassLoader = null;
  8. File addonsDir = new File(repertoireJars);
  9. File[] jars = addonsDir.listFiles(new FilenameFilter() {
  10. public boolean accept(File dir, String name) {
  11.  return name.endsWith(".jar" );
  12. }
  13. });
  14. List urls = new LinkedList();
  15. for (int i = 0; i < jars.length; i++) {
  16. try {
  17.  URL url = jars[i].toURI().toURL();
  18.  urls.add(url);
  19. } catch (MalformedURLException e) {}
  20. }
  21. urls.add(u);
  22. jarClassLoader = new URLClassLoader((URL[])urls.toArray(new URL[urls.size()]));


 
Au moment de la déclaration de l'URLClassLoader, je ne peux pas lui fournir un this.getClass().getClassLoader() car je suis dans un méthode statique (je peux la passer en méthode de classe, mais cela m'ennuierait quelque peu, du fait qu'une seule méthode serait utilisée, ne nécessitant aucune variables de classe).
 
L'erreur ne se produit pas si je fais un jar contenant toutes mes classes utiles (normal en même temps).
 
Merci de l'aide !

Reply

Marsh Posté le 17-03-2010 à 14:58:54    

Si tu es dans une méthode statique, tu peux utiliser NomDeTaClasse.class.getClassLoader()
 
Vu ton code, je suis presque sûr que c'est bien ça le problème.


Message édité par Riokmij le 17-03-2010 à 15:00:21
Reply

Marsh Posté le 19-03-2010 à 14:31:09    

En effet, en lui passant le classloader de la classe incriminée, ca fonctionne :)
 
Merci de l'aide !

Reply

Sujets relatifs:

Leave a Replay

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