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

avec Java Discussion :

Isoler plusieurs instances d'une même application dans une JVM


Sujet :

avec Java

  1. #1
    Candidat au Club
    Homme Profil pro
    Inscrit en
    Août 2011
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Août 2011
    Messages : 3
    Points : 3
    Points
    3
    Par défaut Isoler plusieurs instances d'une même application dans une JVM
    Bonjour,

    Voici le contexte :
    J'ai une application JAVA distribuée. Tous les noeuds font tourner le meme code, mais avec des propriétés différentes lues dans des fichiers de config et/ou dans l'environnement.
    Ce n'est pas moi qui ai développé le programme malheureusement mais j'en ai toutes les sources.
    Ce programme utilise de manière intensive des objets "globaux" (soit par le biais de singletons, soit via l'utilisation directe de variables/méthodes statiques).

    J'ai un deuxième programme (là encore que je n'ai pas réalisé moi-meme), qui est un simulateur pour lequel je dois créer l'interface vers la première application.
    Ce simulateur doit lancer un certain nombre de noeuds et réaliser des mesures. Chacun des noeuds est lancé dans un thread différent et est supposé faire tourner l'application principale.

    Mon problème est que chacun de ces noeuds doit etre totalement isolé des autres : ils ne doivent surtout pas partager les memes instances et ainsi avoir des propriétés statiques différentes pour chaque noeud (mais toujours globales pour tous les threads et objets d'un meme noeud).
    Le code étant le meme, je ne peux pas simplement faire :
    Code JAVA : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    public void run() {
        MonApplication.main(args);
    }
    car sinon chaque noeud partagerait les memes instances...

    Après maintes recherches, j'en suis arrivé à la conclusion que ma seule option serait d'utiliser différents ClassLoader mais j'avoue que je vois mal comment m'en servir...

    Est-ce que la méthode "Thread#setContextClassLoader()" est ce qu'il me faut et si oui quel ClassLoader dois-je lui passer. Me garantit-elle également que tout le code de mon application tournant sur ce noeud va utiliser ce ClassLoader, meme pour les threads fils ?

    Cordialement,
    Jordan

  2. #2
    Rédacteur
    Avatar de bulbo
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Février 2004
    Messages
    1 259
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : Finance

    Informations forums :
    Inscription : Février 2004
    Messages : 1 259
    Points : 1 937
    Points
    1 937
    Par défaut
    Salut,

    Attention, je peux me tromper mais le comportement des ClassLoader par défaut est de vérifier avant de charger quoique ce soit que la classe n'a pas déjà été chargée.

    Donc juste utiliser un setContextClassLoader ne va pas suffire pour ton affaire, il faut aussi que tu ai ton propre ClassLoader qui ne respectera pas le contrat habituel mais rechargera les classes globales genre Singleton.

    Ensuite commence les joyeusetés pour que tout ça reste indépendant tout en permettant à ton simulateur d'éventuellement faire ses mesures.

    Bulbo
    [Java] [NetBeans] [CVS]
    La FAQ Java
    Merci de ne pas me poser de questions techniques par MP.

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

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

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    Pour isoler, il n'y a pas vraiment d'autres choix que de jouer avec le classloader.

    Soit X.jar ton application principale
    Soit Y.jar l'application qui doit tester X.jar en lancat plusieurs noeuds dans la même jvm.

    Il faut
    -> qu'aucune classe de Y.jar ne soit présente ou référencée dans Y.jar
    -> accéder aux classes de X.jar uniquement par reflection (conséquence du point 1 en fait)
    -> Lancer chaque application avec ce genre de code

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    for (int i = 0; i< nbreNoeuds; i++){
      String[] parametres = .....;
      Classloader loader = new URLClassLoader(new URL[]{new File("X.jar").toURI().toURL()};
      Class<?> c = loader.loadClass(nomDuMain);
      Method m = c.getDeclaredMethod("main",parametres.getClass());
      m.invoke(null,parametres)
    }

  4. #4
    Rédacteur
    Avatar de bulbo
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Février 2004
    Messages
    1 259
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : Finance

    Informations forums :
    Inscription : Février 2004
    Messages : 1 259
    Points : 1 937
    Points
    1 937
    Par défaut
    A rajouter aux recommandations de tchize que X.jar ne doit pas faire partie du classpath de la JVM.

    Sinon la première chose que fera l'URLClassLoader sera de demander au system ClassLoader de charger la classe s'il y arrive, il y arrivera et paf les appli ne sont plus isolée.

    Bulbo
    [Java] [NetBeans] [CVS]
    La FAQ Java
    Merci de ne pas me poser de questions techniques par MP.

  5. #5
    Candidat au Club
    Homme Profil pro
    Inscrit en
    Août 2011
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Août 2011
    Messages : 3
    Points : 3
    Points
    3
    Par défaut
    Merci à tous les 2 pour ces réponses.

    @tchize_ Si je lance chacun de mes noeuds avec quelque chose comme toi, est-ce que je dois modifier le code de l'application elle-meme ensuite pour n'utiliser que de la réflection ou les lignes suivantes fonctionneront quand meme tant que j'ai chargé le Main par ta méthode ? :
    Code JAVA : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    String str = MonApp.getProperty(...); // propriété statique
    // ou
    ClassA obj = ClassA.getInstance(); // singleton "classique"
    // ou
    Class.forName(...).newInstance();
    Autre chose, l'application a quelques dépendances externes dans d'autres JAR (que le simulateur n'utilise pas). Cela risque-t-il de poser problème ?

    Enfin, afin d'intégrer au simulateur, je vais devoir créer une nouvelle implémentation de mon module de communication (qui est basé actuellement sur des sockets). Celle-ci va avoir besoin d'une référence vers l'objet du simulateur qui l'a créé (ce seront des objets différents pour chaque noeud). J'ai donc en gros besoin que chaque noeud soit isolé des autres, mais pas totalement du simulateur lui-meme (ils doivent rester indépendants de lui mais tout de meme etre capable de communiquer avec lui, jamais avec les autres noeuds directement par contre). Cela ne risque-t-il pas de poser problème ?

    EDIT : Et qu'en-est-il des threads fils créés par le main de chaque noeud (et il peut y en avoir un bon petit nombre...) ?


    Une autre solution serait de réécrire une grosse partie de l'application principale pour ne plus utiliser du tout de singletons et d'états globaux mais cela prendrait quelques heures de travail donc je préfèrerai éviter si possible

    Merci,
    Jordan

  6. #6
    Rédacteur
    Avatar de bulbo
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Février 2004
    Messages
    1 259
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : Finance

    Informations forums :
    Inscription : Février 2004
    Messages : 1 259
    Points : 1 937
    Points
    1 937
    Par défaut
    Avec la solution de Tchize tu ne devrais pas avoir besoin de toucher à ton application du tout.

    Si les autres jars utilisés par ton application ne contiennent pas de code statique genre singleton qui ne devraient pas être partagé, il suffit qu'ils soient présent dans le classpath pour que ça fonctionne. A condition que ces librairies soient utilisées par ton application mais qu'elles, elles ne connaissent rien de ton application en revanche.

    Si tes applications connaissent toutes ton simulateur, ce n'est pas non plus un problème, la classe de ton simulateur est chargée par le system ClassLoader et est unique dans le système donc personne n'aura de problème avec ça.

    Les Threads utilisent par défaut le ClassLoader avec lequel ils ont été chargés.. donc celui de l'appli particulière à laquelle ils appartiennent, tu ne devrais pas avoir de soucis de ce coté là.

    Par contre l'abus de Singleton et/ou d'état globaux est en général une erreur de design un peu pénalisante, comme tu t'en rends compte actuellement, re-écrire l'application pour ramener ça à la portion congrue ne serait probablement pas une mauvaise idée.

    Bulbo
    [Java] [NetBeans] [CVS]
    La FAQ Java
    Merci de ne pas me poser de questions techniques par MP.

  7. #7
    Candidat au Club
    Homme Profil pro
    Inscrit en
    Août 2011
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Août 2011
    Messages : 3
    Points : 3
    Points
    3
    Par défaut
    Merci bulbo.

    Très bien alors, je vais pouvoir me lancer avec ca en espérant que tout fonctionnera comme il faut

    Citation Envoyé par bulbo
    Par contre l'abus de Singleton et/ou d'état globaux est en général une erreur de design un peu pénalisante, comme tu t'en rends compte actuellement, re-écrire l'application pour ramener ça à la portion congrue ne serait probablement pas une mauvaise idée.
    Je suis parfaitement d'accord avec cela mais malheureusement c'est un assez gros programme que j'ai récupéré de personnes ne le maintenant plus. J'ai déjà du réaliser un gros travail de débogage pour le faire fonctionner correctement et maintenant que je dois l'intégrer au simulateur, je préfère réduire au strict nécessaire les modifications que j'ai à apporter à l'application elle-meme.

    Merci à tous les 2 pour votre précieuse aide
    Jordan

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

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

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    En général, l'application n'utilise pas Thread.currentContextClassloader(), mais ça ne fait pas de mal de le définir quand même .

    Le nouveau thread créés hériteront de la propriétés donc pas de soucis.

    Il faut par contre être bien conscient que cette solution est couteuse en termes de consommation mémoire, chaque classloader prenant une place proportionnelle à la quantité de classes qu'il doit gérer.

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

Discussions similaires

  1. Plusieurs tasks dans une même application
    Par valoo86 dans le forum Android
    Réponses: 1
    Dernier message: 19/05/2012, 10h38
  2. Réponses: 5
    Dernier message: 27/03/2012, 17h02
  3. Réponses: 4
    Dernier message: 20/05/2010, 12h28
  4. Réponses: 6
    Dernier message: 13/11/2009, 16h06
  5. Réponses: 3
    Dernier message: 16/10/2003, 10h22

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