OutOfMemoryError PermGen
Here I look into what is meant when a Java program runs into a OutOfMemoryError: PermGen Space error. I first explain what the permanent generation heap space is, after which I explain the usual cause of the Permgen Space error and I give some pointers on how to avoid it.
Introduction
To understand the error, we have to look into how the jvm memory is structured. There are two memory regions in the JVM: the heap and the stack. Local variables reside on the stack, everything else on the heap. This Java heap memory is structured again into regions, called generations. The longer an object lives, the higher the chance it will be promoted to an older generation. Young generations(such as Eden on Sun JVM)
are more garbage collected than older generations(survivor and tenured on Sun JVM). However, there is also some separate heap space called permanent generation. Since it is a separate region, it is not considered part of the Java Heap space. Objects in this space are relatively permanent. Class definitions are stored here, as are static instances and string pools that have been interned
From experience, the PermGen space issues tend to happen frequently in dev environments really since Tomcat has to load new classes every time it deploys a WAR or does a jspc (when you edit a jsp file). Personally, I tend to deploy and redeploy wars a lot when I’m in dev testing so I know I’m bound to run out sooner or later.
OutOfMemoryError: PermGen Space
The OutOfMemoryError: PermGen Space error occurs when the permanent generation heap is full. Although this error can occur in normal circumstances, usually, this error is caused by a memory leak. In short, such a memory leak means that a classloader and its classes cannot be garbage collected after they have been undeployed/discarded.
To give an example on how this can happen, let’s say we have a Shape class, which is part of a jar in a web application that is deployed on some webserver. In the lib folder of the web server, there is some logging framework present, which has a Log class with the method register(Class clazz) with which classes
can be registered for logging. Let’s say that the Shape class gets registered by this method and the Log class starts keeping a reference to the clazz object. When the Shape class gets undeployed, it is still registered with the Log class. The Log class will still have a reference to it and hence, it will never be garbage
collected. Moreover, since the Shape Class has a reference to its ClassLoader in turn, the ClassLoader itself will never be garbage collected either, and so will none of the classes it loaded.
An even more typical example is with the use of proxy objects. Spring and Hibernate often make proxies of certain classes. Such proxy classes are loaded by a classloader as well, and often, the generated class definitions – which are loaded like classes and stored in permanent generation heap space – are never discarded, which causes the permanent generation heap space to fill up
Avoiding the error
This should theoretically be less of an issue in production environments since you (hopefully) don’t change the codebase on a 10 minute basis. If it still occurs, that just means your codebase (and corresponding library dependencies) are too large for the default memory allocation and you’ll just need to mess around with stack and heap allocation. I think the standards are stuff like:
1. Increasing the PermGen Memory Size
The first thing one can do is to make the size of the permanent generation heap space bigger. This cannot be done with the usual –Xms(set initial heap size) and –Xmx(set maximum heap size) JVM arguments, since as mentioned, the permanent generation heap space is entirely separate from the regular Java Heap space,
and these arguments set the space for this regular Java heap space. However, there are similar arguments which can be used(at least with the Sun/OpenJDK jvms) to make the size of the permanent generation heap bigger:
-XX:MaxPermSize=128m
default is 64m
2. Enable Sweeping
Another way to take care of that for good is to allow classes to be unloaded so your PermGen never runs out:
-XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled
Stuff like that worked magic for me in the past. One thing though, there’s a significant performance trade off in using those, since permgen sweeps will make like an extra 2 requests for every request you make or something along those lines. You’ll need to balance your use with the tradeoffs.
View comments