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 :

[ClassLoader] un dynamisme dynamique?


Sujet :

Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre Expert
    Avatar de ®om
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    2 815
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 2 815
    Par défaut [ClassLoader] un dynamisme dynamique?
    Salut,

    J'ai actuellement 2 problèmes (enfin plutôt un problème et une interrogation), je les mets sur le même post car à mon avis ils ne sont pas si différents que ça.

    Le premier...
    Je voudrais pouvoir changer de look and feel dont la librairie (contenant les classes du look and feel) n'est pas connue à la compilation / création du jar de l'application, mais n'est pas connue non plus au démarrage du programme. On ne la connait que dynamiquement.
    Un programme simple illustrant ceci pourrait être un simple filechooser, et un textfield pour choisir le nom de la classe du look and feel, on choisirait la librairie dans le filechooser, on indiquerait le nom de la classe principale du lookandfeel (le lookandfeelclassname), et on appuierait sur un bouton, et hop, le look and feel se charge...

    Sauf qu'en pratique, je n'ai pas réussi à le faire.
    En effet, j'ai testé 2 choses, dont voici le code (sans la gestion des exceptions) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    // crée mon ClassLoader pour la librairie
    ClassLoader specificClassLoader = createClassLoader();
    // instancie le look and feel
    LookAndFeel look = (LookAndFeel)Class.forName(lookAndFeelName,true,specificClassLoader).newInstance();
    // applique le look and feel
    UIManager.setLookAndFeel(look);
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    // crée mon ClassLoader pour la librairie
    ClassLoader specificClassLoader = createClassLoader();
    // affecte ce ClassLoader au contexte du thread
    Thread.setContextClassLoader(specificClassLoader);
    // applique le look and feel
    UIManager.setLookAndFeel(lookAndFeelName);
    Dans les 2 cas le look and feel est bien chargé, je n'ai pas de ClassNotFoundException.

    Le problème, c'est que dès que mon interface graphique se lance, j'ai le droit à une java.lang.Error (pour chaque composant). Voici celui du JTextArea :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    UIDefaults.getUI() failed: no ComponentUI class for: javax.swing.JTextArea[,0,0,0x0,invalid,alignmentX=0.0,alignmentY=0.0,border=,flags=0,maximumSize=,minimumSize=,preferredSize=,caretColor=,disabledTextColor=,editable=true,margin=,selectedTextColor=,selectionColor=,colums=0,columWidth=0,rows=0,rowHeight=0,word=false,wrap=false]
    java.lang.Error
            at javax.swing.UIDefaults.getUIError(UIDefaults.java:706)
            at javax.swing.MultiUIDefaults.getUIError(MultiUIDefaults.java:117)
            at javax.swing.UIDefaults.getUI(UIDefaults.java:736)
            at javax.swing.UIManager.getUI(UIManager.java:1012)
            at javax.swing.text.JTextComponent.updateUI(JTextComponent.java:332)
            at javax.swing.text.JTextComponent.<init>(JTextComponent.java:306)
            at javax.swing.JTextArea.<init>(JTextArea.java:187)
            at javax.swing.JTextArea.<init>(JTextArea.java:123)
            ...





    Voici ma deuxième interrogation. On peut charger une classe dynamiquement avec
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Class.forName(nomDeLaClass, initializeFlag, classLoader)
    Donc comme ça on peut obtenir un objet qui a accès aux librairies définies dans le ClassLoader, très bien.
    Maintenant, si on veut faire encore plus dynamique, supposons une classe comme ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    class Dynamic {
     
        String[] getLibs() {
            return new String[] { "fichier1.jar", "fichier2.jar" };
        }
     
        void exec() {
            //code utilisant les librairies définies dans getLibs()
        }
     
    }
    On veut charger cette classe par Class.forName, sauf qu'on ne connait pas encore les librairies dont elle a besoin pour exécuter exec(), puisque c'est la classe qui va nous les donner.
    Y'a-t-il une autre solution que de charger la classe une première fois pour récupérer les librairies, et de la recharger une seconde fois avec les librairies dans le ClassLoader?

    Merci d'avance de vos réponses

    ®om

  2. #2
    Membre expérimenté Avatar de coco62
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    237
    Détails du profil
    Informations personnelles :
    Âge : 54
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 237
    Par défaut
    Pour la première partie, c'est comme ci le classloader crée n'avait pas le bon parent ou ne s'y adresse pas.

    Il semble recherche une info dans ton classloader alors qu'elle n'y est pas.
    Ton mode de délégation au parent est il à true ?

    Pour la deuxième partie, cela parait très chaud, une piste serait peut être de mettre ta classe maitresse dans un .jar et de référencé les lib utilisé dans le MANIFEST.MF de ce jar.
    Tu pourrai ensuite lire le MANIFEST pour créer ton classloader avec le jar origine + jar du MANIFEST

  3. #3
    Membre Expert
    Avatar de ®om
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    2 815
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 2 815
    Par défaut
    Première partie résolue, il faut rajouter :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    UIManager.put("ClassLoader", specificClassLoader);
    http://bugs.sun.com/bugdatabase/view...bug_id=4155617

    C'est vraiment horrible les propriétés dont il faut donner le nom, on ne sait pas à quelles valeurs on a le droit...
    (C'est pour ça que je n'aime pas non plus les PropertyChangeListener, et que je préfère utiliser de "vrais" listeners)

    Citation Envoyé par f273345
    Pour la deuxième partie, cela parait très chaud, une piste serait peut être de mettre ta classe maitresse dans un .jar et de référencé les lib utilisé dans le MANIFEST.MF de ce jar.
    Tu pourrai ensuite lire le MANIFEST pour créer ton classloader avec le jar origine + jar du MANIFEST
    C'est ce que je fais pour une partie du programme, mais je me posait la question si tu ne veux pas utiliser de jar ni de fichier texte séparé, mais simplement un .class...

  4. #4
    Expert confirmé
    Avatar de le y@m's
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2005
    Messages
    2 636
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Février 2005
    Messages : 2 636
    Par défaut
    Pour ta deuxième question, la classe Dynamic pourrait avoir un URLClassLoader static dans lequel elle charge les libs lors du chargement de sa première instance.
    Un truc du genre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    class Dynamic {
        private static URLClassLoader libClassLoader = null;
     
        public Dynamic() {
            if(libClassLoader == null) {
                URL[] libUrls = getLibUrls(); // récupère un tableau d'URL des fichiers jar
                libClassLoader = new URLClassLoader(libUrls, getClass().getClassLoader());
            }
        }
     
    // ...
     
    }
    Rq : pas testé, pas de gestion des exceptions, ya juste une idée
    Je ne répondrai à aucune question technique par MP.

    Pensez aux Tutoriels et aux FAQs avant de poster ;) (pour le java il y a aussi JavaSearch), n'oubliez pas non plus la fonction Rechercher.
    Enfin, quand une solution a été trouvée à votre problème
    pensez au tag :resolu:

    Cours Dvp : http://ydisanto.developpez.com
    Blog : http://yann-disanto.blogspot.com/
    Page perso : http://yann-disanto.fr

Discussions similaires

  1. [ClassLoader] Charger une classe extérieure au projet dynamiquement
    Par tiboudchou dans le forum Entrée/Sortie
    Réponses: 3
    Dernier message: 17/01/2007, 14h19
  2. [ClassLoader] Chargement dynamique d'une classe -> problème avec packages !
    Par ymerej dans le forum API standards et tierces
    Réponses: 9
    Dernier message: 31/05/2006, 21h37
  3. [Classpath][Classloader]Chargement dynamique de classes
    Par vberetti dans le forum Général Java
    Réponses: 9
    Dernier message: 08/07/2005, 12h11
  4. Réponses: 4
    Dernier message: 13/05/2002, 16h43
  5. repertoire temp dynamique
    Par killpilot dans le forum C
    Réponses: 2
    Dernier message: 26/04/2002, 16h19

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