2

In our WAR We have three JARs that include the class org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager. One jar has an older version than the others.

This does not cause an issue in our dev or staging environments, however in our production environment a version of the class from a different JAR is loaded causing us a java.lang.NoSuchMethodError on startup. I've taken the exact same WAR that fails in production, and ran it successfully in stage and development.

In Java, what dictates the selection of which jar version of a class is chosen? What would cause that to be different on one box versus another?

danieljimenez
  • 1,390
  • 4
  • 17
  • 26

3 Answers3

3

You can never find out in which order jars will be loaded by Classloader[you can visualize that by using option -verbose:class] or modify that. So now that you know the issue that 2 jars have same file then just place the correct jar else its just a luck of draw whether you get error or not.

EDIT: You can also check this question How to find which jars and in what order are loaded by a classloader?

Community
  • 1
  • 1
Lokesh
  • 7,810
  • 6
  • 48
  • 78
  • Your answer wasn't clear and is very confusing, sorry. I'm not sure what you're getting at. The different load order apparently does have some consistency otherwise I would have experienced this specific exception before. Since it only happens in one environment, there must be something different. – danieljimenez Jun 29 '13 at 03:22
  • Agreed it shows consistency but you can't change the order or force jvm to follow a particular order. Thats what i wanted to say. You can view how things are loaded but can't control it. Hope that clarifies. – Lokesh Jun 29 '13 at 03:23
  • Also wanted to add that java has not disclosed anyhwere about algorithm used for loading jars. So its hidden from us and can be changed as and when they feel. – Lokesh Jun 29 '13 at 03:25
  • @loki +1 - Also the OP has not disclosed any details on the difference between the test, dev and prod environment. With Java, you should never have 3 identically named classes loaded with the same class loader. The packaging of the war must be revisited. – Bruno Grieder Jun 29 '13 at 05:44
  • As fat we I can tell the test and prod environments are exactly the same. – danieljimenez Jun 29 '13 at 12:00
2

Loki is right and the conclusion is going to be the same: the packaging of your war must be revisited. You cannot have three identical named classes loaded by the same class loader and guarantee which one is going to be loaded first.

Every servlet container such as as Jetty, Tomcat (you did not specify which one you are using btw) reimplements some sort of webappClassLoader to guarantee that - according to servlet specifications 2.5+ - the classes of the jars provided in the war are loaded in preference to those of the parent class loader. This is the main difference with the Java provided ÙRLClassLoader` which searches the parent class loader first. The servlet specifications do not specify more on how the search should be conducted.

In other words, if you change servlet container or just the version of your servlet container, the behavior of your war may change again. The underlying filesystem may have an impact as well (case sensitive/insensitive), etc...

==> You must repackage your war.

Assuming you use Tomcat 7, here is a link to the findClass method of Tomcat WebappClassLoader

Bruno Grieder
  • 28,128
  • 8
  • 69
  • 101
0

Jar loading order is determined by the file system. If the default order changes in the file system the load order changes. The file system order is determined by the OS, and at least on some OS's the order of creation in the end determines the load order. Note, that's not the create date of the file, but the actual time a file is created on the file system. Hence you can have identical looking file systems, which exhibit different behaviour in jar loading. There isn't a good way to control the order in the end, so you are back to making sure you don't have identical jars of different versions in your class path.

leblonk
  • 187
  • 8