How does java choose a .JAR library version











up vote
0
down vote

favorite












For various historical reasons, I have an old java application which shares a local lib/ directory of library .JARs with some other applications. In this directory is a number of versioned copies of the same library, for example:



...
log4j-1.2.16.jar
log4j-1.2.17.jar
slf4j-api-1.7.5.jar
slf4j-api-1.7.21.jar
slf4j-log4j12-1.7.5.jar
slf4j-log4j12-1.7.9.jar
...


When my java app starts, how does it decide which .jar file to load? As far as I know, the CLASSPATH is just set to ./lib/. But it uses the Tanuki Service wrapper to start, so I'm not 100% sure of this.



I can't delete any of these existing .JARs, is there a way to specify exactly which .JARs my app will use ?



After this old application was patched, now I'm getting a NoClassDefFoundError, and I suspect the app is loading an older (or newer) version of a .JAR that conflicts with another library (BoneCP and slf4j).










share|improve this question
























  • Having the same library in different versions in the classpath is always bad. Either only one version is used, then you could easily remove the other or both are used (because they do not contain exactly the same classes) but then you almost certainly get conflicts because one version uses the common classes from the other library.
    – Henry
    Nov 8 at 4:39















up vote
0
down vote

favorite












For various historical reasons, I have an old java application which shares a local lib/ directory of library .JARs with some other applications. In this directory is a number of versioned copies of the same library, for example:



...
log4j-1.2.16.jar
log4j-1.2.17.jar
slf4j-api-1.7.5.jar
slf4j-api-1.7.21.jar
slf4j-log4j12-1.7.5.jar
slf4j-log4j12-1.7.9.jar
...


When my java app starts, how does it decide which .jar file to load? As far as I know, the CLASSPATH is just set to ./lib/. But it uses the Tanuki Service wrapper to start, so I'm not 100% sure of this.



I can't delete any of these existing .JARs, is there a way to specify exactly which .JARs my app will use ?



After this old application was patched, now I'm getting a NoClassDefFoundError, and I suspect the app is loading an older (or newer) version of a .JAR that conflicts with another library (BoneCP and slf4j).










share|improve this question
























  • Having the same library in different versions in the classpath is always bad. Either only one version is used, then you could easily remove the other or both are used (because they do not contain exactly the same classes) but then you almost certainly get conflicts because one version uses the common classes from the other library.
    – Henry
    Nov 8 at 4:39













up vote
0
down vote

favorite









up vote
0
down vote

favorite











For various historical reasons, I have an old java application which shares a local lib/ directory of library .JARs with some other applications. In this directory is a number of versioned copies of the same library, for example:



...
log4j-1.2.16.jar
log4j-1.2.17.jar
slf4j-api-1.7.5.jar
slf4j-api-1.7.21.jar
slf4j-log4j12-1.7.5.jar
slf4j-log4j12-1.7.9.jar
...


When my java app starts, how does it decide which .jar file to load? As far as I know, the CLASSPATH is just set to ./lib/. But it uses the Tanuki Service wrapper to start, so I'm not 100% sure of this.



I can't delete any of these existing .JARs, is there a way to specify exactly which .JARs my app will use ?



After this old application was patched, now I'm getting a NoClassDefFoundError, and I suspect the app is loading an older (or newer) version of a .JAR that conflicts with another library (BoneCP and slf4j).










share|improve this question















For various historical reasons, I have an old java application which shares a local lib/ directory of library .JARs with some other applications. In this directory is a number of versioned copies of the same library, for example:



...
log4j-1.2.16.jar
log4j-1.2.17.jar
slf4j-api-1.7.5.jar
slf4j-api-1.7.21.jar
slf4j-log4j12-1.7.5.jar
slf4j-log4j12-1.7.9.jar
...


When my java app starts, how does it decide which .jar file to load? As far as I know, the CLASSPATH is just set to ./lib/. But it uses the Tanuki Service wrapper to start, so I'm not 100% sure of this.



I can't delete any of these existing .JARs, is there a way to specify exactly which .JARs my app will use ?



After this old application was patched, now I'm getting a NoClassDefFoundError, and I suspect the app is loading an older (or newer) version of a .JAR that conflicts with another library (BoneCP and slf4j).







java






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 8 at 4:12

























asked Nov 8 at 4:01









Kingsley

1,6951918




1,6951918












  • Having the same library in different versions in the classpath is always bad. Either only one version is used, then you could easily remove the other or both are used (because they do not contain exactly the same classes) but then you almost certainly get conflicts because one version uses the common classes from the other library.
    – Henry
    Nov 8 at 4:39


















  • Having the same library in different versions in the classpath is always bad. Either only one version is used, then you could easily remove the other or both are used (because they do not contain exactly the same classes) but then you almost certainly get conflicts because one version uses the common classes from the other library.
    – Henry
    Nov 8 at 4:39
















Having the same library in different versions in the classpath is always bad. Either only one version is used, then you could easily remove the other or both are used (because they do not contain exactly the same classes) but then you almost certainly get conflicts because one version uses the common classes from the other library.
– Henry
Nov 8 at 4:39




Having the same library in different versions in the classpath is always bad. Either only one version is used, then you could easily remove the other or both are used (because they do not contain exactly the same classes) but then you almost certainly get conflicts because one version uses the common classes from the other library.
– Henry
Nov 8 at 4:39












2 Answers
2






active

oldest

votes

















up vote
1
down vote



accepted










If you are going to share lib directories like that, then each application needs to list the JAR files that it uses explicitly on the classpath. If you use a wildcard classpath entry (e.g. "lib/*"), then it is not specified which versions of the JARs will be used. The manual entry states:




Class Path Wild Cards



Class path entries can contain the base name wildcard character (), which is considered equivalent to specifying a list of all of the files in the directory with the extension .jar or .JAR. For example, the class path entry mydir/ specifies all JAR files in the directory named mydir. A class path entry consisting of * expands to a list of all the jar files in the current directory. Files are considered regardless of whether they are hidden (have names beginning with '.').



....



The order in which the JAR files in a directory are enumerated in the
expanded class path is not specified and may vary from platform to
platform and even from moment to moment on the same machine. A
well-constructed application should not depend upon any particular
order. If a specific order is required, then the JAR files can be
enumerated explicitly in the class path.







share|improve this answer





















  • Thanks Stephen, this was exactly the solution - java -cp lib/jarfile1.jar;lib/jarfile2.jar; etc etc. I had to do this for 11 jar libs.
    – Kingsley
    Nov 8 at 5:34












  • I guess .... you could also do it with symlinks. Create a "lib" directory for each application and populate it with symlinks to the appropriate versions of the JARs. But explicitly naming the JARs in your classpath via a wrapper script is more robust,
    – Stephen C
    Nov 8 at 5:41


















up vote
2
down vote













Which jar first in classpath that is picked up when JVM classloader is looking for a class. So you can try to add those jars in different order to check which one breaks your application






share|improve this answer





















    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53201380%2fhow-does-java-choose-a-jar-library-version%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    1
    down vote



    accepted










    If you are going to share lib directories like that, then each application needs to list the JAR files that it uses explicitly on the classpath. If you use a wildcard classpath entry (e.g. "lib/*"), then it is not specified which versions of the JARs will be used. The manual entry states:




    Class Path Wild Cards



    Class path entries can contain the base name wildcard character (), which is considered equivalent to specifying a list of all of the files in the directory with the extension .jar or .JAR. For example, the class path entry mydir/ specifies all JAR files in the directory named mydir. A class path entry consisting of * expands to a list of all the jar files in the current directory. Files are considered regardless of whether they are hidden (have names beginning with '.').



    ....



    The order in which the JAR files in a directory are enumerated in the
    expanded class path is not specified and may vary from platform to
    platform and even from moment to moment on the same machine. A
    well-constructed application should not depend upon any particular
    order. If a specific order is required, then the JAR files can be
    enumerated explicitly in the class path.







    share|improve this answer





















    • Thanks Stephen, this was exactly the solution - java -cp lib/jarfile1.jar;lib/jarfile2.jar; etc etc. I had to do this for 11 jar libs.
      – Kingsley
      Nov 8 at 5:34












    • I guess .... you could also do it with symlinks. Create a "lib" directory for each application and populate it with symlinks to the appropriate versions of the JARs. But explicitly naming the JARs in your classpath via a wrapper script is more robust,
      – Stephen C
      Nov 8 at 5:41















    up vote
    1
    down vote



    accepted










    If you are going to share lib directories like that, then each application needs to list the JAR files that it uses explicitly on the classpath. If you use a wildcard classpath entry (e.g. "lib/*"), then it is not specified which versions of the JARs will be used. The manual entry states:




    Class Path Wild Cards



    Class path entries can contain the base name wildcard character (), which is considered equivalent to specifying a list of all of the files in the directory with the extension .jar or .JAR. For example, the class path entry mydir/ specifies all JAR files in the directory named mydir. A class path entry consisting of * expands to a list of all the jar files in the current directory. Files are considered regardless of whether they are hidden (have names beginning with '.').



    ....



    The order in which the JAR files in a directory are enumerated in the
    expanded class path is not specified and may vary from platform to
    platform and even from moment to moment on the same machine. A
    well-constructed application should not depend upon any particular
    order. If a specific order is required, then the JAR files can be
    enumerated explicitly in the class path.







    share|improve this answer





















    • Thanks Stephen, this was exactly the solution - java -cp lib/jarfile1.jar;lib/jarfile2.jar; etc etc. I had to do this for 11 jar libs.
      – Kingsley
      Nov 8 at 5:34












    • I guess .... you could also do it with symlinks. Create a "lib" directory for each application and populate it with symlinks to the appropriate versions of the JARs. But explicitly naming the JARs in your classpath via a wrapper script is more robust,
      – Stephen C
      Nov 8 at 5:41













    up vote
    1
    down vote



    accepted







    up vote
    1
    down vote



    accepted






    If you are going to share lib directories like that, then each application needs to list the JAR files that it uses explicitly on the classpath. If you use a wildcard classpath entry (e.g. "lib/*"), then it is not specified which versions of the JARs will be used. The manual entry states:




    Class Path Wild Cards



    Class path entries can contain the base name wildcard character (), which is considered equivalent to specifying a list of all of the files in the directory with the extension .jar or .JAR. For example, the class path entry mydir/ specifies all JAR files in the directory named mydir. A class path entry consisting of * expands to a list of all the jar files in the current directory. Files are considered regardless of whether they are hidden (have names beginning with '.').



    ....



    The order in which the JAR files in a directory are enumerated in the
    expanded class path is not specified and may vary from platform to
    platform and even from moment to moment on the same machine. A
    well-constructed application should not depend upon any particular
    order. If a specific order is required, then the JAR files can be
    enumerated explicitly in the class path.







    share|improve this answer












    If you are going to share lib directories like that, then each application needs to list the JAR files that it uses explicitly on the classpath. If you use a wildcard classpath entry (e.g. "lib/*"), then it is not specified which versions of the JARs will be used. The manual entry states:




    Class Path Wild Cards



    Class path entries can contain the base name wildcard character (), which is considered equivalent to specifying a list of all of the files in the directory with the extension .jar or .JAR. For example, the class path entry mydir/ specifies all JAR files in the directory named mydir. A class path entry consisting of * expands to a list of all the jar files in the current directory. Files are considered regardless of whether they are hidden (have names beginning with '.').



    ....



    The order in which the JAR files in a directory are enumerated in the
    expanded class path is not specified and may vary from platform to
    platform and even from moment to moment on the same machine. A
    well-constructed application should not depend upon any particular
    order. If a specific order is required, then the JAR files can be
    enumerated explicitly in the class path.








    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered Nov 8 at 4:34









    Stephen C

    509k69556909




    509k69556909












    • Thanks Stephen, this was exactly the solution - java -cp lib/jarfile1.jar;lib/jarfile2.jar; etc etc. I had to do this for 11 jar libs.
      – Kingsley
      Nov 8 at 5:34












    • I guess .... you could also do it with symlinks. Create a "lib" directory for each application and populate it with symlinks to the appropriate versions of the JARs. But explicitly naming the JARs in your classpath via a wrapper script is more robust,
      – Stephen C
      Nov 8 at 5:41


















    • Thanks Stephen, this was exactly the solution - java -cp lib/jarfile1.jar;lib/jarfile2.jar; etc etc. I had to do this for 11 jar libs.
      – Kingsley
      Nov 8 at 5:34












    • I guess .... you could also do it with symlinks. Create a "lib" directory for each application and populate it with symlinks to the appropriate versions of the JARs. But explicitly naming the JARs in your classpath via a wrapper script is more robust,
      – Stephen C
      Nov 8 at 5:41
















    Thanks Stephen, this was exactly the solution - java -cp lib/jarfile1.jar;lib/jarfile2.jar; etc etc. I had to do this for 11 jar libs.
    – Kingsley
    Nov 8 at 5:34






    Thanks Stephen, this was exactly the solution - java -cp lib/jarfile1.jar;lib/jarfile2.jar; etc etc. I had to do this for 11 jar libs.
    – Kingsley
    Nov 8 at 5:34














    I guess .... you could also do it with symlinks. Create a "lib" directory for each application and populate it with symlinks to the appropriate versions of the JARs. But explicitly naming the JARs in your classpath via a wrapper script is more robust,
    – Stephen C
    Nov 8 at 5:41




    I guess .... you could also do it with symlinks. Create a "lib" directory for each application and populate it with symlinks to the appropriate versions of the JARs. But explicitly naming the JARs in your classpath via a wrapper script is more robust,
    – Stephen C
    Nov 8 at 5:41












    up vote
    2
    down vote













    Which jar first in classpath that is picked up when JVM classloader is looking for a class. So you can try to add those jars in different order to check which one breaks your application






    share|improve this answer

























      up vote
      2
      down vote













      Which jar first in classpath that is picked up when JVM classloader is looking for a class. So you can try to add those jars in different order to check which one breaks your application






      share|improve this answer























        up vote
        2
        down vote










        up vote
        2
        down vote









        Which jar first in classpath that is picked up when JVM classloader is looking for a class. So you can try to add those jars in different order to check which one breaks your application






        share|improve this answer












        Which jar first in classpath that is picked up when JVM classloader is looking for a class. So you can try to add those jars in different order to check which one breaks your application







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 8 at 4:04









        Ivan

        4,4891720




        4,4891720






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.





            Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


            Please pay close attention to the following guidance:


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53201380%2fhow-does-java-choose-a-jar-library-version%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            這個網誌中的熱門文章

            Post-Redirect-Get with Spring WebFlux and Thymeleaf

            Xamarin.form Move up view when keyboard appear

            JBPM : POST request for execute process go wrong