Mike,
The PermGen space is the area where classes, methods and the like are stored. There are two possibilities to the cause of this OutOfMemory:

- The best case: the application is simply loading too many classes, and they do not fit in the PermGen space. In this case, it will be enough to increase the PermGen size - The worst case: you are experiencing a problem of class (or classloader) garbage collection. Unfortunately, by your description, it seems to be your case.

The problem is that, when you reload the webapp, the JVM is not being able to "garbage collect" the old web-app version. This effect is accumulative, and the more times you reload your webapp, the more space is not being freed in the PermGen space.

The cause for this behaviour is that there are strong references that are not being freed when your webapp is stopped. Due to these references, the garbage collector is not able to finalize the referenced classes, or the classloader they where loaded with.

This is not really a Tomcat problem, but your webapp's. There are several wide-spread programming patterns that have this effect when used in a webapp. The following are two examples that I usually find in the projects I try to "fix":

- The singleton pattern creates a hard reference of the class in the class itself. This makes the class unloadable. I prefer to use the commons-discovery DiscoverSingleton class. By using this class, you can get singleton instances of the classes you need. The advantage is that you can add a ServletContextListener to your webapp, and call its static release() method within contextDestroyed, so all singleton instances are safely released. This library provides more discovery patterns that can be useful in other situations.

- It is very common to find a declaration like this:

   private static final Log log = LogFactory.getLog(MyClass.class);

 From the commons-logging API documentation:

"LogFactory needs to keep a static map of LogFactory objects keyed by context classloader; when the webapp is "undeployed" this means there is still a reference to the undeployed classloader preventing the memory used by all its classes from being reclaimed."

If you are using commons-logging, the LogFactory provides the "releaseAll" method, that can be used to release all the internal references, and can also be called from the ServletContextListener.contextDestroyed() method. In fact, the commons-logging documentation itself recommends to use this method in servlet containers ;-) You can also use the org.apache.commons.logging.impl.ServletContextCleaner class.

There are other patterns that have the same effects, and they should all be avoided if you want your webapp to be "really" reloadable :-)

Perhaps, it would be a good idea to create a section in the Tomcat WIKI to list these patterns, and their workarounds :-)

Best Regards (and Happy Christmas!),
Rodrigo Ruiz

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to