views:

705

answers:

4

Hi,

We have hosted our web applications on Tomcat 6.0.18 and experienced the following problem:

There are two web apps WebApp1 and WebApp2, both are same system but of different versions.

Now the problem is when the tomcat has been running for a week or longer time then sometimes system gives NoClassDefFoundError ! also we got some strange issue where the Class Loader of WebApp1 has loaded the class present in the jar of WebApp2 ! The same jar is also present in WebApp1 but the versions are different.

When we restarted the Tomcat everything started working fine ! Our JRE is 1.5.10

Please let me know if you have encountered such issues.

Regards, Jatan Porecha

+1  A: 

I've encountered many, many flavors of classloader weirdness with Tomcat - even if you don't perform any classloader code yourself, it's very easy for Tomcat itself to produce problems. The most common problem appears to be repeatedly unloading and reloading a webapp leaks classloaders and eventually runs Tomcat out of memory.

The most common reason I've seen for version mismatches is that Tomcat makes sure some classes and jars (part of Tomcat itself) are ahead of any others in your webapp classpath - commons-logging seems to be the most common example - and it's possible for classloaders to be loaded, unloaded, or kept around when you wouldn't expect.

Can you provide a few more details - if the jar is from a third-party there is a good chance someone has seen the issue before. If it's your own jar, then do you have any of your own classloader code in the application?

Chris
A: 

Thanks Chris for your response.

The jar has been part of the system and having some common classes which are shared by other processes.

Lets call that jar comutils.jar So the scenario is something like,

WebApp1 (ver 1)
  |
  |- comutils.jar (ver 1)
        |
        |- MailSender.class (ver 1)


WebApp2 (ver 2)
  |
  |- comutils.jar (ver 2)
        |
        |- MailSender.class (ver 2)

This MailSender class is singleton.

Now sometimes what happens is that whenever code of WebApp1 calls any method of MailSender after retrieving its instance using getInstance method then the actually call goes to MailSender (ver 2) instead of ver 1 !!

Hope this would give you some lead.

jatanp
I think it's _far_ more likely you have an extra version of comutils.jar deployed somewhere in WebApp1's classpath than it is that the Tomcat Classloader is suddenly loading classes from outside it's classpath... check that MailSender.class is only located in one place.
matt b
Yes we have checked and verified that both jars are different and placed in different webapps..
jatanp
+1  A: 

I still don't have enough rep to add a comment, so I'll have to post another answer. :)

This sounds like somehow the MailSender.class is getting loaded into Tomcat, not into each individual webapp. WebApp2 loads it first and it works, even though it is loaded into all of Tomcat not private to WebApp2. When WebApp1 needs the class, it already sees its loaded into the Tomcat parent and does not try to load one private to WebApp1.

I'd first suggest you check your Tomcat, JRE, etc... directories to see if there is somehow a copy of the jar or the class in those paths. After that I would manually remove the class from each of the two jar files and restart Tomcat or the web applications to see what happens - you would expect it to fail and produce a stack trace, and that will tell you where your class is first loaded and who is attempting to load it. (For instance, from the class name, it's possible you have a mail API, loaded into the Tomcat JVM, that loads the class - into Tomcat not into your webapp).

Chris
+1  A: 

Is there a particular reason you are hosting 2 versions of the exact same code on the same server?

Having 2 different jars with the exact same name, containing classes in the same namespace, and having identical class names seems like it would cause all sorts of issues (not the least of which is human error).

James Van Huis