IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Java Discussion :

peut-on modifier un archive jar (compilé) sans avoir le projet original ?


Sujet :

Java

  1. #1
    Nouveau membre du Club
    Inscrit en
    Avril 2009
    Messages
    41
    Détails du profil
    Informations forums :
    Inscription : Avril 2009
    Messages : 41
    Points : 30
    Points
    30
    Par défaut peut-on modifier un archive jar (compilé) sans avoir le projet original ?
    bonsoir; dans le cadre dans mon PFE, j'ai développé une plateforme multi-agents où le développeur n'as besoin que le JAR de cette plate-forme pour construire ses applications(SMA : Système Multi-Agents). Je suis entrain de développer quelques exemples pour tester et valider cette plate-forme. Dans un exemple je construit une classe AgentVendeur qui hérite de classe AgentAtomique(qui se trouve dans le JAR). je l'ai instancie et ça marche; mais quand j'utilise des méthodes qui manipule le type AgentAtomique dans le classe de ce JAR et je fais le cast à AgentVendeur; une exception se produit. J'ai pu régler cette exception de telle sorte que la classe AgentVendeur doit se trouve dans le jar de la plate-forme. Mais je ne comprend pas pourquoi la classe AgentVendeur doit se trouver dans le JAR de la plateforme???? et C'est pourquoi je me demande si on peut modifier un archive jar (compilé) sans avoir le projet original ? parce que le développeur n'aura pas le code source de l'application; il travaillera qu'avec son JAR. ET est ce que se trouve un autre moyen pour régler ce problème sans ajouter cette classe au JAR. merci

  2. #2
    Expert confirmé
    Avatar de slim_java
    Homme Profil pro
    Enseignant
    Inscrit en
    Septembre 2008
    Messages
    2 272
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : Tunisie

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Septembre 2008
    Messages : 2 272
    Points : 4 539
    Points
    4 539
    Par défaut
    salut
    qu'est ce que tu prêtant dire par "on peut modifier un archive jar"
    tu peut nous dire c'est quoi l'exception ?

  3. #3
    Nouveau membre du Club
    Inscrit en
    Avril 2009
    Messages
    41
    Détails du profil
    Informations forums :
    Inscription : Avril 2009
    Messages : 41
    Points : 30
    Points
    30
    Par défaut
    bonjour; en fait la classe AgentVendeur qui hérite de la classe AgentAtomique doit être dans le jar pour que l'exemple marche (je ne comprends pas pourquoi!!!!!) donc est ce qu'il existe une méthode pour ajouter des classes .java ou\et .class dans le JAR? sans avoir besoin du code source de l'application pour créer un nouveau JAR qui contient cette classe. Car l'utilisateur de cette plateforme ne possèdera que le JAR.
    L'exception se lève quand je fais le casting de type AgentAtomique à AgentVendeur; en effet j'ai une méthode getAgent() qui retourne AgentAtomique; quand je cast la valeur à AgentVendeur une exception se lève. Ce pb se pose si la classe AgentVendeur ne se trouve pas dans le JAR. quand j'ai inséré la classe AgentVendeur dans le code source et j'ai recrée le JAR; tous marche bien. JE NE COMPRENDS PAS POURQUOI?????????.
    merci

  4. #4
    Nouveau membre du Club
    Inscrit en
    Avril 2009
    Messages
    41
    Détails du profil
    Informations forums :
    Inscription : Avril 2009
    Messages : 41
    Points : 30
    Points
    30
    Par défaut L'exception
    j'ai re-exécuter l'exemple (je n'ai mis pas la classe AgentVendeur dans le Jar je l'ai mis dans le projet qui contient l'exemple). L'exception est java.lang.ClassCastException: AgentVendeur cannot be cast to AgentVendeur. Quelqu'un peut m'expliquer??????

  5. #5
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Points : 48 804
    Points
    48 804
    Par défaut
    Citation Envoyé par aroussi_sanaa Voir le message
    j'ai re-exécuter l'exemple (je n'ai mis pas la classe AgentVendeur dans le Jar je l'ai mis dans le projet qui contient l'exemple). L'exception est java.lang.ClassCastException: AgentVendeur cannot be cast to AgentVendeur. Quelqu'un peut m'expliquer??????
    Tu as deux fois la classe AgentVendeur présente dans des classloaders différents. C'est la cause de ton erreur. Il y a la classe présente dans le classloader utlisé losque tu fait "(AgentVendeur) xxxx" et la classe retournée par la méthode que tu as appelée. Comme ces classes sont chargées par des classloader différents, elles sont différentes. Regarde déjà pourquoi cette classe est en double dans tes classloader, se sont des cas extrèmement rares et qui résultent souvent d'une application qui bidouille de travers avec ses classloaders.

  6. #6
    Modérateur
    Avatar de nouknouk
    Homme Profil pro
    Inscrit en
    Décembre 2006
    Messages
    1 655
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Décembre 2006
    Messages : 1 655
    Points : 2 161
    Points
    2 161
    Par défaut
    salut,

    normalement utiliser une classe d'une lib tierce ne pose aucun souci particulier. De nombreuses librairies Java non open source existent et permettent de manipuler les classes du jar correspondant à la librairie tierce sans souci (pour autant que les classes soient déclarées publiques).

    Je penche personnellement plutôt pour un souci de paramétrage des projets dans ton environnement.

    L'exception "java.lang.ClassCastException: AgentVendeur cannot be cast to AgentVendeur" pourrait être causée par le fait que la classe AgentVendeur existe deux fois dans ton projet où tu rencontres le problème: le nom est identique mais chacune se réfère à une version de la classe présente dans un jar différent.

    Par exemple, si ton projet inclut le code source de AgentVendeur d'une part, mais que AgentVendeur est également inclue par l'intermédiaire du JAR ajoutée au classpath de ton projet lors de son exécution: le nom est identique mais pour Java ce sont deux classes totalement séparées ; il se comporte comme si on avait deux classes ayant deux noms différents.

    EDIT: grilled par tchize

  7. #7
    Nouveau membre du Club
    Inscrit en
    Avril 2009
    Messages
    41
    Détails du profil
    Informations forums :
    Inscription : Avril 2009
    Messages : 41
    Points : 30
    Points
    30
    Par défaut
    bonsoir tchiz, vous avez raison j'utilise bcq des classloades pour instancier des classes dynamiquement. En fait la classe AgentVendeur est instancié dynamiquement; l'utilisateur n'as qu'à entrer le nom et le chemin de la classe puis nous instancions un agent vendeur qu'on lui ajoute des compétences. Ces compétences sont aussi des classes qu'on va les instancier. SVP, vous pouvez l'expliquer où se trouve le problème exactement ?
    et comment peut-on régler ce problème.

    Dans notre application on a pas utilisé des classloade, mais des URLloader pour charger l'adresse de la classe. et d'aprés ce que j'ai lu sur les ClassLoader, ils existent dans la JVM pour charger une classe lorsque on demande de l'exécuter. Donc comment toujours utiliser le meme ClassLoader ?

    merci

  8. #8
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Points : 48 804
    Points
    48 804
    Par défaut
    Il nous faudrais voir ton code su comment tu manipule tes classloader. Aussi, il faudrait, pour bien faire un shcema ou croquis de ta hierarchie de classloaders avec l'endroit ou les classes concernées sont respectivement instanciées et castées

  9. #9
    Nouveau membre du Club
    Inscrit en
    Avril 2009
    Messages
    41
    Détails du profil
    Informations forums :
    Inscription : Avril 2009
    Messages : 41
    Points : 30
    Points
    30
    Par défaut
    je t'explique un peu l'architecture de notre plate-forme (application). Elle se compose d'une librairie des classes et d'un environnement graphique. la librairie des classes contient tous les classes nécessaires à créer des agents atomiques et faire communiquer ces agents entre eux. Tous les agents doivent hériter de la classe mère AgentAtomique. Un agent peut acquérir dynamiquement des compétences qui présentent leurs capacités. Ces compétences doivent hériter de la classe competence et elles sont acquises dynamiquement (on les instancie dynamiquement). L'environnement graphique sert à créer des agents atomiques(cliquant sur le bouton creerAgent) et leurs ajoutent des compétences dynamiquement(cliquant sur le bouton AjouterCompetence). L'environnement graphique propose une autre façon de créer SMA (Système Multi Agent); il permet d'ajouter une classe contenant tous le programme de SMA (tous les agents); instancie cette classe et affiche les résultats. Bon le problème se pose lorsque j'utilise la deuxième façon de créer SMA. comme les boutons créerAgent ne crée que des agents atomiques donc pour créer un autres type d'agents je dois utiliser la classe main pour l'instancier. donc j'ai créer une classe AgentVendeur qui hérite de la classe AgentAtomique; j'ai crée une classe main qui instancie ce type d'agent et tout fonctionne correctement. mais quand j'ajoute une compétence à cet agent vendeur l'exception se lève
    Merci d'avance

  10. #10
    Nouveau membre du Club
    Inscrit en
    Avril 2009
    Messages
    41
    Détails du profil
    Informations forums :
    Inscription : Avril 2009
    Messages : 41
    Points : 30
    Points
    30
    Par défaut voici un aperçu sur mon code
    bonsoir,
    Tous les agents doivent hériter de la classe mère AgentAtomique AgentAtomique.java.
    La méthode ajouterCompétence permet à l'agent d'acquérir dynamiquement des compétences.
    la classe Interface présente l'environnement graphique de la plateforme. Le bouton ajouterMain permet d'ajouter une classe qui hérite de la classe Main Main.java. et le bouton exécuterMain permet d'exécuter cette classe.
    le code du bouton ajouterMain est le suivant :
    try {
    URL chemins[] = { new URL(MonFiltre.chemin(file.getPath())) };
    URLClassLoader loader = new URLClassLoader(chemins);
    String chaine = file.getName();
    String nom = MonFiltre.nomClass(chaine);
    Class cl = loader.loadClass(nom);
    Class c = cl.getSuperclass();
    if (c.getName().equals("dz.esi.edma.interfacegraphique.Main")) {
    main.put(nom, MonFiltre.chemin(file.getPath()));
    ListMain.addElement(nom);
    ....}
    }
    le code du bouton exécuterMain est le suivant :
    Object[] tab = jListMain.getSelectedValues();
    String classe = tab[0].toString();
    String chemin = main.get(classe);
    try {
    URL chemins[] = { new URL(chemin) };
    URLClassLoader loader = new URLClassLoader(chemins);
    Class cl = loader.loadClass(classe);
    Object o = cl.newInstance();
    Class[] type = new Class[] { String[].class };
    Method m = o.getClass().getMethod("LeMain", type);
    Object arg1 = null;
    m.invoke(o, arg1);
    ........
    Dans mon exemple j'ai définit un agent vendeur qui possède un catalogue
    public class AgentVendeur extends AgentAtomique {
    public HashMap<String,Integer> catalogue = null;
    .....}
    Et j'ai ajouté et exécuté la classe M M.javaqui hérite de Main.
    Tout marche. mais quand j'ajoute la compétence UpdateCatalogue à "l'agent V" l'exception se produit au niveau de l'instruction
    ((AgentVendeur)getAgent()).catalogue.put(titre, prix);
    La méthode getAgent() retourne l'agent possédant cette compétence (retourne le type AgentAtomique).
    La classe UpdateCompétence hérite de la classe CompétenceAction CompétenceAction.java Compétence.java.
    A l'ajout de cette compétence, la méthode Action sera ajoutée à la file des tâche de l'agent qui l'exécute par la méthode exécuter du cycle de vie actif (voir la classe AgentAtomique).
    si vous avez d'autre questions vous n'avez qu'à demander. merci d'avance tchiz

  11. #11
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Points : 48 804
    Points
    48 804
    Par défaut
    on peux voir le stacktrace de ton exception et l'endroit du code ou ca se produit?

  12. #12
    Nouveau membre du Club
    Inscrit en
    Avril 2009
    Messages
    41
    Détails du profil
    Informations forums :
    Inscription : Avril 2009
    Messages : 41
    Points : 30
    Points
    30
    Par défaut
    re, voici le stracktrace
    java.lang.ClassCastException: AgentVendeur cannot be cast to AgentVendeur
    at UpdateCatalogue.Action(UpdateCatalogue.java:40)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at dz.esi.edma.noyau.AgentAtomique$CycleDeVieActif.execute(AgentAtomique.java:144)
    at dz.esi.edma.noyau.AgentAtomique.run(AgentAtomique.java:576)
    at java.lang.Thread.run(Unknown Source)
    L'instruction qui lève l'exception est :
    ((AgentVendeur)getAgent()).catalogue.put(titre, prix);
    de la classe UpdateCatalogue UpdateCatalogue.java

  13. #13
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Points : 48 804
    Points
    48 804
    Par défaut
    ton AgentVendeur, retourné par getAgent a été chargé par un classloader différent de celui utilisé pour charger ta classe UpdateCatalogue. Peux-t-on voir le code qui fait "new AgentVendeur" ainsique que le code qui fait "new UpdateCatalogue()"

    L'origine du problème est probablement à trouver dans le code que tu utilise pour tes classloader. Tu fait à chaque fois des opération du type "je crée un classloader, j'instancie un classe, je jette le classloader". Il faut savoir que pour que des classes soit identique dans java, il faut qu'elle aient le même nom, mais aussi qu'elle proviennent du même classloader, sinon c'est ClassCastException. Comme a chaque fois tu crée un nouveau classloader même si c'est sur les mêmes jars, tu termines avec pleins de classes chargées dans des classloaders différent et incompatibles entre elles.

  14. #14
    Nouveau membre du Club
    Inscrit en
    Avril 2009
    Messages
    41
    Détails du profil
    Informations forums :
    Inscription : Avril 2009
    Messages : 41
    Points : 30
    Points
    30
    Par défaut
    Bonsoir,
    La classe M fais new AgentVendeur(). Cette classe est chargée par l'action du bouton exécuterMain.
    La classe UpdateCatalogue est chargée par la méthode ajouterCompétence de la classe AgentAtomique.
    vous trouvez les codes dans les messages précédents.
    j'ai compris le problème mais comment peut-on gérer les ClasseLoaders?
    merci

  15. #15
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Points : 48 804
    Points
    48 804
    Par défaut
    Citation Envoyé par aroussi_sanaa Voir le message
    j'ai compris le problème mais comment peut-on gérer les ClasseLoaders?
    Il faut revoir la logique de ton code, elle est beaucoup trop dispersée. Pour le moment tu es parti sur une logique "j'ai besoin d'une classe, alors je charge le <<plugin>> avec un classloader, je crée la classe qui m'intéresse, puis j'oublie le classloader. Et je fais ça a plein d'endroits du code. Tu va devoir centraliser un peu tout cas, et stocker aussi tout ca.

    Par exemple, tu peux faire ceci:

    une interface "Plugin", qui contiendrais plusieurs méthodes descriptives (getMain(), getCompetences(), etc). Tu charge le jar à un endroit précis de ton code, tu instancie la class Plugin (je te conseille d'ailleurs pour ca de jeter un oeil sur la notion de service ici et ici qui est destinée à ce genre de chose en java) et tu stocke dans une tableau ou une Map le plugin ainsi chargée:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    private List<Plugin> mesPlugins;
    private List<AgentAtomique> mesAgents;
    //....
    // code de chargement d'un plugin demandé par l'interface
    Plugin p = <code appelant le classloader>
    if (p!=null){
        mesPlugins.add(p);
        AgentAtomique a = p.getMain().créerAgent();
        if (a!=null)
            for (Competence c : p.getCompetences())
                a.addCompetence(c);
    }
    Ensuite, toute manipulations de tes agents se ferait uniquement à travers "mesPlugins.get(index)" et plus jamais tu n'instancie de classloader.

Discussions similaires

  1. Peut-on modifier le titre de l'alert
    Par MokhTelnet dans le forum Général JavaScript
    Réponses: 6
    Dernier message: 17/05/2010, 10h46
  2. Peut on modifier des fichiers Excel sans qu'il soient ouvert?
    Par the-geut dans le forum Macros et VBA Excel
    Réponses: 4
    Dernier message: 16/04/2010, 10h45
  3. Réponses: 3
    Dernier message: 17/07/2006, 17h04
  4. [jar] Comment modifier un fichier jar
    Par newfsch dans le forum JBuilder
    Réponses: 5
    Dernier message: 18/07/2004, 14h25
  5. Réponses: 16
    Dernier message: 18/07/2003, 17h16

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo