Order of loading jar files from lib directory
It's all described in Tomcat's ClassLoading HOW-TO. It's not necessarily in alphabetic order. If you observed that behaviour, it should absolutely not be relied upon if you intend to keep your webapp portable across servers. For example, Tomcat 6 "coincidentally" orders it, but Tomcat 8 does not.
Summarized, the loading order is as follows:
- bootstrap/system (
JRE/lib
, thenserver.loader
) - webapp libraries (
WEB-INF/classes
, thenWEB-INF/lib
) - common libraries (
common.loader
, thenTomcat/lib
) - webapp-shared libraries (
shared.loader
)
If you would like to guarantee that JAR X is loaded after JAR Y, then you'd need to put JAR X in one of the places which appears later in the listing above.
There are exceptions however, which are mentioned in the tomcat docs
Lastly, the web application class loader will always delegate first for JavaEE API classes for the specifications implemented by Tomcat (Servlet, JSP, EL, WebSocket). All other class loaders in Tomcat follow the usual delegation pattern.
That means if a webapp contains any JavaEE classes (javax.*
), then it will be ignored by tomcat.
For each loader, the classes are just loaded by the JVM in the order whenever they needs to be imported/executed and are not loaded yet.
Why would changing directory order of jar files in WEB-INF/lib cause a NoClassDefFoundError in Tomcat 8?
The line:
Caused by: java.lang.NoClassDefFoundError: Could not initialize class org.geotools.referencing.datum.DefaultEllipsoid
means that the class DefaultEllipsoid
is found but to be valid, there is some other class that need to be loaded but this fail. Another class is invalid.
It is this class that perhaps is duplicated with two very differents version, or one version is used for compilation, another version with different method signature at runtime.
Also, from tomcat8, the applicative jar files in WEB-INF/lib
are NOT loaded according to alphabetical order anymore. I think there was a document with this on tomcat site, but for now I don't find it anymore but I found a regression bug (won't fix) on tomcat bugzilla bug 57129
This classloader stuff means that if you change some stuff on the WEB-INF/lib
and restart Tomcat, then there is a bit of random class loading that make your application load one way or the other if there is duplicate jar version.
To sum up: Check the DefaultEllipsoid
import and check if there is duplicate on those class. Your build also need to be cleaned to use the same version as runtime (I hope you use tools like maven
to do the build)
Spring-boot inner jar files loading order? (embedded tomcat)
The jars in BOOT-INF/lib
are always added to Spring Boot’s class loader in the order in which they appear in the jar. This means that if you have the same class file or resource declared in multiple jars, the same one will always win across multiple runs of your application, irrespective of operating system, Java version, etc. This holds true even if you're using Spring Boot's support for automatically unpacking certain jars at runtime.
Spring Boot also packages a BOOT-INF/classpath.idx
index file in each jar that it builds. It lists all of the nested jars "in the order that they should be added to the classpath". If you unzip the jar file such that the jars in BOOT-INF/lib
are then ordered by the filesystem, if you continue to use Spring Boot's JarLauncher
to launch the application it will honour the order in the index.
Spring Boot contains tests, such as these, that verify the ordering of the classpath, both when launching an application using java -jar
and when using java org.springframework.boot.loader.JarLauncher
.
How to change order of Jars loaded from WEB-INF/lib?
As far as I know, there is no concept of alphabetical loading of jar files.
Your packaging model needs to be revisited - packaging both the patch.jar and original.jar is going to cause you grief.
Why do you need the original jar when the patch.jar contains the fixed ones?
Even if you want to retain the original.jar and patch.jar (am assuming it is complete), you can try and use the class loader hierarchy to ensure that the patch.jar is loaded first compared to original.jar always.
For e.g you can package original.jar at a shared library level with the class loading policy of parent_last and keep the patch.jar in your WEB-INF/lib.
Though i am suggesting this as an alternative, you should consider replacing orginal.jar with the patch.jar or have the patch contain all the changed files (and removing them from the original.jar)
HTH
Manglu
How to find which jars and in what order are loaded by a classloader?
The short answer is no. Classloaders are not required to expose their search logic.
However, if your classloader instance happens to be URLClassLoader or a subclass, then you do have access to the list of jars/directories, via the getURLs()
method. Per the doc for this class, those URLs will be searched in order.
In practice, if you're trying to find out where a class is being loaded from, Steve's answer is probably more useful.
class loading in tomcat on demand when 2 versions of a lib are present?
From link posted by @GyroGearless
Therefore, from the perspective of a web application, class or resource loading looks in the following repositories, in this order:
•Bootstrap classes of your JVM
•/WEB-INF/classes of your web application
•/WEB-INF/lib/*.jar of your web application
•System class loader classes (described above)
•Common class loader classes (described above)
If the web application class loader is configured with
<Loader delegate="true"/>
then the order becomes:•Bootstrap classes of your JVM
•System class loader classes (described above)
•Common class loader classes (described above)
•/WEB-INF/classes of your web application
•/WEB-INF/lib/*.jar of your web application
If classloader needs to load class X then once it finds it in one place it will not look for it in any other places.
Lib conflict is possible if you place one version of your dependency (say MySQL
driver) to $JAVA_HOME/jre/lib/ext
and another one into /WEB-INF/lib
Related Topics
Java Division by Zero Doesnt Throw an Arithmeticexception - Why
Why Equal Operator Works for Integer Value Until 128 Number
How to Ensure Hashcode() Is Consistent with Equals()
Comparing Float/Double Values Using == Operator
Where Is the Javabean Property Naming Convention Defined
Instance Method Reference and Lambda Parameters
How to Add Unique Jcomboboxes to a Column in a Jtable (Java)
How to Pass List from Java to Oracle Procedure
Dependency Injection in Struts2 Accessing Session Scoped Beans
Run Exe Which Is Packaged Inside Jar File
Preserving Parameter/Argument Names in Compiled Java Classes
Replace All Occurrences of a String Using Stringbuilder
Sending Mail Attachment Using Java
Why Can't a Generic Type Parameter Have a Lower Bound in Java
Why Does Arraylist Have "Implements List"