Could anyone explain the order in which jar files are loaded from the lib directory within Tomcat? Is it alphabetically? Randomly? Or some other order?
5 Answers
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.
Actually, it is alphabetical order! (Within a specific directory, e.g. the 'lib' directory that the original poster mentions.)
More specifically, if you look at the source for Tomcat 6, in class FileDirContext
, the method list()
calls Arrays.sort()
on the array of file names of jars that are found.
I have tested this manually as well. I create a war with a JSP that calls HelloWorld.getGreeting()
, and put two nearly identical jars containing slightly different versions of HelloWorld
into the WEB-INF/lib directory. One says "Hello, world", the other "Goodbye, cruel world".
If I name the "Hello, world" version a.jar, and the "goodbye" version b.jar, and restart Tomcat, I get the "Hello" text. If I name the jars the other 'way round and restart Tomcat, I get the "Goodbye" text.
As far as I have been able to determine, this behaviour is NOT documented, NOT specified, and should NOT be relied on. But it is alphabetical -- for now.
I totally agree to the answer provided by BalusC. Only point to add is when it comes to loading a JAR from respective classloader it does check alphabetical order.
I had a situation to load "XSSFWorkbook" in my web application to read data from excel sheet and had two JARS "poi-ooxml-3.9.jar" and "org.eclipse.birt.runtime_4.3.1.v20130918-1142.jar" with same class name and package structure. I simply remaned the later so in its alphabetical order comes next to the earlier one and it did a trick for me. Just wanted to share the same.
Good Luck
In our WebSphere env, different machine loads the jar in different order. So I agree with user2193008. We encounter class loader issue in Production env where same code works fine in lower env. We fixed issue by removing duplicate jar in lib, for example, there are two version of spring jars, spring_v1.jar and spring_v2.jar, if classloader loads v1 first, code works fine, but if classloader loads v2 first, trouble.