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 :

Classpath et jar file


Sujet :

Java

  1. #1
    Membre habitué
    Inscrit en
    Janvier 2005
    Messages
    491
    Détails du profil
    Informations forums :
    Inscription : Janvier 2005
    Messages : 491
    Points : 172
    Points
    172
    Par défaut Classpath et jar file
    Hello,

    Lorsque je lance mon appli sous netbeans et que j'excute le bout de code suivant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    String classPath = System.getProperty("java.class.path");
    String [] jars = classPath.split(File.pathSeparator);
    for (String jar : jars) {
        System.out.println("Checking "+jar);
    }
    J'obtient bien l'ensemble des .jar que j'ai indiqué a Netbeans et faisant parti du projet (avec en plus des chemins vers certains répertoires, comme le répertoire source).

    Lorsque j'execute ce même bout de code, mais en ayant lancé l'application à partir du .jar construit sous netbeans, je n'obtient que le nom du .jar que j'ai executé.

    Je pense avoir trouvé l'explication à cela, mais pas de solution: les .jar dont dépendent mon projet sont situés dans un dossier lib, tel que la hiérarchie de mes fichiers est la suivante:

    prog.jar
    lib/*.jar
    Je n'ai donc pas inclu ces .jar dirèctement dans le jar de mon application. Mon fichier manifest contient les infos suivantes:
    Manifest:
    Manifest-Version: 1.0

    Ant-Version: Apache Ant 1.7.1

    Created-By: 14.2-b01 (Sun Microsystems Inc.)

    Main-Class: my.app.core.Main

    Class-Path: lib/1.jar lib/2.jar ...
    J'ai l'impression que si mes .jar étaient inclus dans le jar dirèctement ca fonctionnerait.

    Comment faire pour signifier que ces .jar font partis de la propriétée java.class.path et obtenir la liste complète des jar inclus dans le classpath?

    Merci d'avance!

  2. #2
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Salut,



    Ton manifest est correct, mis à part peut-être pour les lignes vides...

    La propriété "java.class.path" comporte uniquement le classpath défini lors du lancement du programme, et non pas forcément tous les éléments du-dit classpath. Ce dernier peut en effet être modifier pendant le déroulement du programme et après son lancement...


    Il peut être assez difficile de récupérer le contenu exact du classpath...

    Pourquoi as-tu besoin de la liste des jars ???

    a++

  3. #3
    Membre habitué
    Inscrit en
    Janvier 2005
    Messages
    491
    Détails du profil
    Informations forums :
    Inscription : Janvier 2005
    Messages : 491
    Points : 172
    Points
    172
    Par défaut
    En fait c'est une des librairies tierce qui a besoins des jars contenus dans le classpath pour fonctionner corrècteent... Ca pose donc un problème important vu que je ne peux pas modifier cette librairie sans tout recompiler...

    C'est assez embêtant. Ya t-il un autre moyen de récupérer l'ensemble des jars? Je pourrait l'utiliser pour contourner le problème...

    Ce qui est étonnant c'est que le programme semble pourtant bien voir l'ensemble des librairies vu qu'il tourne sans problème.

  4. #4
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Si c'est simplement pour faire marcher le programme tout est OK il n'y a rien à faire.


    La propriété "java.class.path" contient les infos initial du classpath, et donc uniquement le jar principal dans le cas de l'appel d'un jar exécutable.

    Mais cela ne veut pas dire que le classpath de l'application ne comporte QUE cela... bien au contraire.

    a++

  5. #5
    Membre habitué
    Inscrit en
    Janvier 2005
    Messages
    491
    Détails du profil
    Informations forums :
    Inscription : Janvier 2005
    Messages : 491
    Points : 172
    Points
    172
    Par défaut
    Le programme fonctionne dans l'ensemble, sauf pour la partie nécessitant les JAR. En fait, la librairie que j'utilise regarde cette propriété pour vérifier la présence de pluggins. Ceux-ci sont normalement justement situés dans mon dossier /lib, mais ca ne fonctionne pas pour les raisons que j'ai cité.

    Y'a t-il une propriété équivalante à "java.class.path" permettant de récupérer l'ensemble des jar du classpath de l'application?

  6. #6
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par adiGuba Voir le message
    Il peut être assez difficile de récupérer le contenu exact du classpath...

    Pourquoi as-tu besoin de la liste des jars ???

    a++

  7. #7
    Membre habitué
    Inscrit en
    Janvier 2005
    Messages
    491
    Détails du profil
    Informations forums :
    Inscription : Janvier 2005
    Messages : 491
    Points : 172
    Points
    172
    Par défaut
    Ah... Par difficile tu entends donc impossible si je comprends bien

    Je vais donc fouiller un peu quand même

    merci de tes réponses en tt cas;

  8. #8
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par vinzzzz Voir le message
    Ah... Par difficile tu entends donc impossible si je comprends bien
    Non : assez compliqué car cela dépend du classloader. Tu as donc plusieurs cas particulier et tu n'es même pas sûr de récupérer toutes ces infos...


    Mais ce que je ne comprend toujours pas, c'est pourquoi tu as besoin de cela ???


    a++

  9. #9
    Membre habitué
    Inscrit en
    Janvier 2005
    Messages
    491
    Détails du profil
    Informations forums :
    Inscription : Janvier 2005
    Messages : 491
    Points : 172
    Points
    172
    Par défaut
    L'application que je développe utilise une librairie externe qui possède une fonctionalité qui va charger automatiquement un certain nombre de classes en se basant sur l'ensemble des JARs contenus dans la propriétée "java.class.path".

    En résumé: ils chargent l'ensemble des jar contenus dans java.class.path, puis ils parcourent chacun d'entre eux, et récupèrent les classes qui vont bien.

    Le problème est que manifestement, java.class.path ne contient pas ce qu'ils espéraient: Selon eux, il devrait contenir le classpath du système d'après ce que j'ai lu dans leur doc:

    A String[] containing the fully qualified names of the jar files to examine for descriptor classes. In general this can be set to NULL, in which case the system classpath is examined for available jar files.
    Ce bout de doc corespond à l'argument 2 de la fonction ci-dessous, qui se charge de charger les classes:

    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
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
     
        public static List<String> getDescriptorClassNameByPackage(
                String packageName, String[] jarFileNames) {
     
            if (packageName == null || packageName.equals("")) {
                packageName = "org.openscience.cdk.qsar.descriptors.molecular";
            }
     
            String[] jars;
            if (jarFileNames == null) {
                String classPath = System.getProperty("java.class.path");
                jars = classPath.split(File.pathSeparator);
            }
            else {
                jars = jarFileNames;
            }
     
            List<String> classlist = new ArrayList<String>();
     
            for (String jar : jars) {
                System.out.println("Checking jar file " + jar);
                JarFile jarFile;
                try {
                    jarFile = new JarFile(jar);
                    Enumeration enumeration = jarFile.entries();
                    while (enumeration.hasMoreElements()) {
                        JarEntry jarEntry = (JarEntry) enumeration.nextElement();
                        if (jarEntry.toString().indexOf(".class") != -1) {
                            String tmp = jarEntry.toString().replace('/', '.').replaceAll(
                                    ".class", "");
                            if (!(tmp.indexOf(packageName) != -1)) {
                                continue;
                            }
                            if (tmp.indexOf('$') != -1) {
                                continue;
                            }
                            if (tmp.indexOf("Test") != -1) {
                                continue;
                            }
                            if (!classlist.contains(tmp)) {
                                classlist.add(tmp);
                            }
                        }
                    }
                }
                catch (IOException e) {
                }
            }
            return classlist;
        }
    En gros, quand je suis dans netbeans, mon println pour chaque jar affiche bien l'ensemble des jars, et lorsque je suis en dehors de netbeans (lorsque je déploie mon appli), ca ne fonctionne plus et je n'ai plus que mon propre jar qui s'affiche.

    Bref je suppose que c'est leur manière de faire qui déconne, et je vais essayer de trouver une astuce pour la contourner.

  10. #10
    Membre habitué
    Inscrit en
    Janvier 2005
    Messages
    491
    Détails du profil
    Informations forums :
    Inscription : Janvier 2005
    Messages : 491
    Points : 172
    Points
    172
    Par défaut
    Dans la doc de sun il est pourtant indiqué :

    "java.class.path": Path used to find directories and JAR archives containing class files. Elements of the class path are separated by a platform-specific character specified in the path.separator property.
    J'ai du mal a comprendre pourquoi dans ce cas il ne contient que mon jar executable? Il ne tiens pas compte de ce qui est dans le manifest?

  11. #11
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par vinzzzz Voir le message
    J'ai du mal a comprendre pourquoi dans ce cas il ne contient que mon jar executable? Il ne tiens pas compte de ce qui est dans le manifest?
    Il contient le classpath initial, qui ne correspond pas forcément au classpath pendant toutes la durée de l'application. Et lorsque tu lance un jar exécutable le classpath correspond uniquement à ce jar. Ce n'est qu'après que sont rajouté les autres jar lié...

    Le classpath peut évoluer pendant le cycle de l'application, et il est potentiellement infini, alors que la variable "java.class.path" correspond uniquement à son état initial.




    Apparemment tu cherches à récupérer la liste des classes d'un package, ce qui n'est pas possible aisément justement à cause des différentes sources que peut prendre le classpath.


    Tu peux peut-être récupérer tous les jar en recherchant tous les fichiers MANIFEST :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    	Enumeration<URL> urls = ClassLoader.getSystemResources("META-INF/MANIFEST.MF");
    	for ( URL url : Collections.list(urls) ) {
    		System.out.println(url);
    	}
    a++

  12. #12
    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 807
    Points
    48 807
    Par défaut
    Je vais proposer du bash& crash. On est d'accord, la librairie est mal foutue, elle n'aurait pas à faire çà, mais elle le fait (sic) et aurait du etre basé sur un api de Service présente depuis jdk 1.4. Solution

    Tu scanne toi même à la main le contenu de lib/*.jar et tu établit comme convention que ton application sera distribuée avec cette structure. Ensuite tu crée un string regroupant tous ces jar avec séparateur et tu fait un System.setProperty("java.lang.classpath",classpathToutPourriPourLibrairiePourrie) et la librairie sera contente
    Simple et rapide, pas besoin de scanner le classpath réel.

    Autre solution, ne pas mettre les lib dans ton manifest, mais plutot passer par un .bat ou un .sh qui fait un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    java -cp=monCode.jar;lib/lib1.jar;lib/lib2.jar ma.classe.Principale
    et la librairie tierce sera aussi contente.

    Troisième solution: utilise la première solution, mais au lieu de construire la String, la prendre hardcodée dans un fichier de config ou sur la ligne de commande

    Dans tous les cas, ca vaut mieux de d'essayer d'extirper l'info depuis le classloader car ca nécessitera de la bidouille pas garantie.

  13. #13
    Membre habitué
    Inscrit en
    Janvier 2005
    Messages
    491
    Détails du profil
    Informations forums :
    Inscription : Janvier 2005
    Messages : 491
    Points : 172
    Points
    172
    Par défaut
    Oui j'ai opté pour l'option je stocke le chemin vers le jar de la librairie dans un fichier properties et j'update le classpath.

    J'ai également pu constater que le répertoire de travail n'est pas le même suivant que l'on lance l'appli via. la console (java -jar ...) ou en double cliquant sur le jar executable dirèctement (auquel cas le répertoire de travail est mon home).

    Enfin normalement tout cela est réglé
    Merci a vous pour votre aide!

  14. #14
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par vinzzzz Voir le message
    J'ai également pu constater que le répertoire de travail n'est pas le même suivant que l'on lance l'appli via. la console (java -jar ...) ou en double cliquant sur le jar executable dirèctement (auquel cas le répertoire de travail est mon home).
    C'est normal : le répertoire de travail dépend de la manière dont tu lances le programme.

    Si tu ne lances pas le programme de la même manière, tu n'auras pas le même répertoire de travail.

    a++

Discussions similaires

  1. jar file
    Par Asnidren dans le forum JDeveloper
    Réponses: 4
    Dernier message: 29/01/2007, 14h15
  2. problème avec jar file
    Par jayjay.f dans le forum AWT/Swing
    Réponses: 17
    Dernier message: 04/12/2006, 00h40
  3. Jar File's import
    Par badi082 dans le forum Eclipse Java
    Réponses: 2
    Dernier message: 27/11/2006, 16h21
  4. Comment lire un jar file dans javascript ?
    Par Battosaiii dans le forum Général JavaScript
    Réponses: 4
    Dernier message: 04/10/2006, 13h23
  5. prblème création Jar file
    Par phileme dans le forum Eclipse Java
    Réponses: 2
    Dernier message: 16/06/2006, 21h19

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