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]