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 :

Charger une classe dans le classloader courant


Sujet :

Java

  1. #1
    Rédacteur

    Homme Profil pro
    Geek entrepreneur
    Inscrit en
    Novembre 2004
    Messages
    1 224
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Geek entrepreneur

    Informations forums :
    Inscription : Novembre 2004
    Messages : 1 224
    Points : 2 373
    Points
    2 373
    Par défaut Charger une classe dans le classloader courant
    Bonjour,

    J'ai une partie du code dans une appli qui est généré au démarrage et chargé dans un classloader.
    Pour charger les classes, je créé un classloader :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    loader = new URLClassLoader(new URL[]{tmpDirFile.toURL()}, Thread.currentThread().getContextClassLoader() );
    puis je charge les classes une par une de la facon suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Class klass = loader.loadClass(nomdelaclasse);
    Mon souci c'est que j'ai besoin de ces classes a un tout autre endroit et qu'apparemment elles ne sont pas trouvées, ce qui parait logique puisque les classes sont dans ce classloader et non dans le classloader courant.

    Si je tente de faire loadClass sur le classloader courant ca ne marche pas puisque le classloader courant ne connait pas les chemins (url) de mes classes et il n'y a pas de méthode pour lui en rajouter.

    Une idée ?

  2. #2
    Membre confirmé Avatar de djsnipe
    Inscrit en
    Mai 2008
    Messages
    440
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 440
    Points : 493
    Points
    493
    Par défaut
    Le problème vient effectivement du fait que ton nouveau ClassLoader est hiérarchiquement de niveau inférieur, et que dans l'arborescence des ClassLoader de ton application, il doit représenter une feuille.
    Bilan, aucun autre niveau ne peut s'appuyer sur les classes qu'il est le seul à connaître.

    Pour pallier le problème, il faut que tu définises ce ClassLoader comme un parent ou bien directement comme le ClassLoader "courant". La notion de "courant" désigne le ClassLoader associé au Thread en cours d'exécution. Je suppose que ton application est de type J2SE (pas de J2EE donc), et il faut voir de quelle manière tu gères tes Threads, mais tu peux changer le ClassLoader d'un Thread par sa méthode setContextClassLoader.

    Si toutes tes libs sont dans le classpath, le ClassLoader système est celui par défaut et ton ClassLoader "loader" qui charge les class dynamique est un de ses fils. Donc utilises directement "loader" comme ClassLoader pour tes threads, sauf si d'autres subtilités sont présentes.

  3. #3
    Rédacteur

    Homme Profil pro
    Geek entrepreneur
    Inscrit en
    Novembre 2004
    Messages
    1 224
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Geek entrepreneur

    Informations forums :
    Inscription : Novembre 2004
    Messages : 1 224
    Points : 2 373
    Points
    2 373
    Par défaut
    en fait si je suis bien dans du J2EE, il s'agit d'une facade web service dont les beans et la facade sont générés à la volée puis exposé par xfire.

    Et effectivement je n'avais pas pensé à faire ceci :

    Thread.currentThread().setContextClassLoader(loader);
    Mais cela fonctionne correctement. Je vais encore faire des tests mais il semblerait que ce soit ok.

    Merci

  4. #4
    Membre confirmé Avatar de djsnipe
    Inscrit en
    Mai 2008
    Messages
    440
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 440
    Points : 493
    Points
    493
    Par défaut
    Cool.
    En fait, c'est juste qu'en J2EE il existe une hiérarchie de ClassLoader (système, pour le serveur d'appli, pour l'EAR, pour le WAR dans l'EAR ...) et que selon les serveurs d'appli, ils peuvent se comporter/configurer de différentes manières, et c'est souvent prise de tête

  5. #5
    Rédacteur

    Homme Profil pro
    Geek entrepreneur
    Inscrit en
    Novembre 2004
    Messages
    1 224
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Geek entrepreneur

    Informations forums :
    Inscription : Novembre 2004
    Messages : 1 224
    Points : 2 373
    Points
    2 373
    Par défaut
    aie, tout ne pouvait pas être aussi beau.

    En fait lors d'un appel aux webservices, jaxb utilise Thread.currentThread().getContextClassLoader() et cherche ensuite certaines classes comme le ObjectFactory afin de faire la désérialisation du message SOAP.

    Or, il s'agit d'un thread de tomcat dont le classloader courant est le WebappClassLoader et non mon autre classloader que j'ai positionné sur un autre thread.
    Bref, impossible de désérialiser mes beans. Il faut sans doute repenser la facon dont s'est fait.

  6. #6
    Membre confirmé Avatar de djsnipe
    Inscrit en
    Mai 2008
    Messages
    440
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 440
    Points : 493
    Points
    493
    Par défaut
    Pas si vite
    Je ne connais pas xfire, mais pour JAXB, lors de la construction du context, tu peux lui spécifier un ClassLoader spécifique (javadoc + infos ici).

  7. #7
    Rédacteur

    Homme Profil pro
    Geek entrepreneur
    Inscrit en
    Novembre 2004
    Messages
    1 224
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Geek entrepreneur

    Informations forums :
    Inscription : Novembre 2004
    Messages : 1 224
    Points : 2 373
    Points
    2 373
    Par défaut
    Tout a fait, je suis effectivement tombé dans le cas décrit et j'avais vu cette doc cependant jaxb est appelé par la servlet xfire.
    Je vais essayer une autre méthode qui est de surcharger la méthode la servlet xfire pour changer le classloader courant à chaque fois qu'elle traitera une requête. Je teste

  8. #8
    Rédacteur

    Homme Profil pro
    Geek entrepreneur
    Inscrit en
    Novembre 2004
    Messages
    1 224
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Geek entrepreneur

    Informations forums :
    Inscription : Novembre 2004
    Messages : 1 224
    Points : 2 373
    Points
    2 373
    Par défaut
    Le test a fonctionné, les surcharges de doPost et doGet de la servlet xfire pour setter le classloader du thread courant ont marché.

  9. #9
    Membre confirmé Avatar de djsnipe
    Inscrit en
    Mai 2008
    Messages
    440
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 440
    Points : 493
    Points
    493
    Par défaut
    Peux-tu poster un exemple pour les prochains visiteurs ?

  10. #10
    Rédacteur

    Homme Profil pro
    Geek entrepreneur
    Inscrit en
    Novembre 2004
    Messages
    1 224
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Geek entrepreneur

    Informations forums :
    Inscription : Novembre 2004
    Messages : 1 224
    Points : 2 373
    Points
    2 373
    Par défaut
    Ok, par contre c'est quand même assez lié à la facon dont je sauve le classloader dans le générateur de facade. Ce bout de code n'est pas très intéressant en soi sans comprendre les posts ci dessus.

    Pour archive donc :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    /**
     * Extension of XFireSpringServlet to override the contextClassLoader by the one store by 
     * the current context of the application who generate the beans
     *
     */
    public class XFireSpringServlet extends org.codehaus.xfire.spring.XFireSpringServlet
    {
        /**
         * 
         */
        private static final long serialVersionUID = 3916444003701340148L;
     
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException
        {
            ClassLoader loader = ApplicationCoreContextSingleton.getCurrentContext().getClassLoader();
            if ( loader != null )
            {
                Thread.currentThread().setContextClassLoader(loader);
            }
            super.doPost(req, res);
        }
     
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
        {
            ClassLoader loader = ApplicationCoreContextSingleton.getCurrentContext().getClassLoader();
            if ( loader != null )
            {
                Thread.currentThread().setContextClassLoader(loader);
            }
            super.doGet(request, response);
        }
    }

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Charger une classe contenue dans un .dll
    Par NLS le pingouin dans le forum Langage
    Réponses: 4
    Dernier message: 21/05/2010, 15h42
  2. Réponses: 2
    Dernier message: 01/03/2010, 13h46
  3. Réponses: 3
    Dernier message: 13/02/2007, 17h54
  4. [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
  5. [C#] [.NET] Lecture d'une classe dans un fichier
    Par niPrM dans le forum Windows Forms
    Réponses: 4
    Dernier message: 18/05/2004, 08h57

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