Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to avoid undeployment memory leaks in Tomcat?

This question is for anyone who's ever tested the "Find leaks" button in the Tomcat manager and got some results like this:

The following web applications were stopped (reloaded, undeployed), but their classes from previous runs are still loaded in memory, thus causing a memory leak (use a profiler to confirm):
/leaky-app-name

I'm assuming this has something to do with that "Perm Gen space" error you often get with frequent redeployments.

So what I'm seeing in jconsole when I deploy is that my loaded classes goes from about 2k to 5k. Then you would think an undeployment should drop them back down to 2k but they remain at 5k.

I've also tried using the following JVM options:

-XX:+CMSClassUnloadingEnabled -XX:+UseConcMarkSweepGC -XX:+CMSPermGenSweepingEnabled

I did see VERY minor dips in the amount of Perm Gen space used but not what I expected and the loaded class counts did not drop.

So is there a way to configure Tomcat or design your app to unload better on an undeployment? Or are we stuck with restarting the server after some major debugging sessions?

Tomcat version output:

Server version: Apache Tomcat/6.0.29
Server built: July 19 2010 1458
Server number: 6.0.0.29
OS Name: Windows 7
OS Version: 6.1
Architecture: x86
JVM Version: 1.6.0_18-b07
JVM Vendor: Sun Microsystems Inc.

Update:

Thanks to celias' answer I decided to do a little more digging and I think I determined the culprit to be in my application thanks to CXF, Spring and JAXB.

After I learned how to profile a Java application, I pointed the profiler at Tomcat and took some heap dumps and snapshots to see what the objects and classes looked like in memory. I discovered that some of the enumerations from my XML schema used in my CXF/JAXB (wsdl2java) generated classes were lingering after an undeployment. According to my heap dump it looks like the objects were tied to a Map. Disclaimer: I admit I'm still a little green with profiling and tracing an object's call tree can be challenging in Java.

Also I should mention that I didn't even invoke the service, just deployed then undeployed it. The objects themselves appeared to be loaded via reflection initiated from Spring on deployment. I believe I followed the convention for setting up a CXF service in Spring. So I'm not 100% sure if this is Spring/CXF, JAXB, or reflection's fault.

As a side note: the application in question is a web service using Spring/CXF and the XML happens to be a rather complex schema (an extension of NIEM).

like image 200
waltwood Avatar asked Dec 30 '10 18:12

waltwood


People also ask

How do you avoid memory leaks?

To avoid memory leaks, memory allocated on heap should always be freed when no longer needed.

How does Tomcat detect memory leaks in Java?

Go into the heap dump settings for your server Right-click on Tomcat from the sidebar on the left-hand side then select 'Heap Dump'. Figure 2: Heap Dump: Click on the 'OQL Console' button.

What is memory leak in Tomcat?

Cause 1 - Memory LeaksBecause the PermGen has a finite size, reloading the flawed application just a handful of times can trigger an OutOfMemoryError, or OOME. Eliminating retained references to the web application class loader will allow Garbage Collection to function properly, preventing these errors.


2 Answers

If you want to make sure not to cause leaks you have to do the following:

  • Make sure your web application does not use any java classes that are in the web container shared libraries. If you have any shared libraries, make sure there is no strong references to the objects in those libraries
  • Avoid using static variables, especially on java objects like HashTable, Sets, etc. If you need to, make sure that you call remove to release the objects with the maps, lists...

Here is also a good article on ThreadLocal and MemoryLeaks - http://blog.arendsen.net/index.php/2005/02/22/threadlocals-and-memory-leaks-revisited/

like image 138
celias Avatar answered Nov 16 '22 00:11

celias


Tomcat 7 is supposed to bring improvements in this area. See Features of Apache Tomcat 7, section titled No More Leaks!

They believe they can now cope with a lot of memory leaks caused by the web applications. Unfortunately, it's still in beta.

Other than that, I can just say that I've made the same experience and haven't found a solution. Deploying usually requires restarting Tomcat afterwards. I have no idea who the culprit is: my web application, Tomcat, Hibernate, Tapestry or several of them.

like image 39
Codo Avatar answered Nov 16 '22 01:11

Codo