Java tips, observations, bugs and problems from the world of Spring, Weblogic, Oracle, MySQL and many other technologies...

Friday, 22 July 2011

java.lang.OutOfMemoryError: PermGen

Like most people, I’ve experienced the pain of a java.lang.OutOfMemoryError: PermGen exception when developing applications using a Weblogic server. It usually occurs when I’m running my Weblogic server with Sun’s Hotspot JVM and, like most people I’ve complained that the developers at Oracle should fix this problem, but the question is, can they?

The short answer is no, as the problem is caused by a memory leak somewhere in your application. In order to explain what’s happening, the first thing to do is to briefly explain what permGen space is.

Gen or generation space is all to do with heap space. There are three types of generation space: new gen, old gen and perm gen. Now, very simplistically, objects comprise of code that runs plus their data. So, when you deploy your application, your classes are loaded by their classloader(s) the code (i.e. the stuff that runs plus class meta data) is loaded into perm gen space, whilst its data is stuck into new gen space.

Just sticking with the new and old gen thing for one moment, I think that the idea here is that new gen is garbage collected often, and hence transient objects are stored here. If, after a certain number of passes of the GC the object is still in use, then it’s moved to old gen, which is GC’ed less often.

When you undeploy your application, your classloader and all the classes it loaded are marked for garbage collection. That’s the theory anyway... however, if something holds on to a class reference or references (i.e. the memory leak), then those classes aren’t marked for garbage collection and are left discarded by the container but still in memory. You then redeploy your application taking up more perm gen space and after a few deploys and undeploys, then you get the java.lang.OutOfMemoryError: PermGen exception.

The 'fix', or work around, to the problem is to increase your server's perm gen space and this is done by using the following compiler argument:

-XX:MaxPermSize=128m

The default value is 64m or 64MB. Sun, and now Oracle, document all this on their website

Finally, you can try using the JRocket JVM, it’s a different kettle of fish to the Sun Hotspot JVM, but at the end of the day, you’ll just have to either find your memory leak or restart the server.

That's not a VM bug. That's "just" a memory leak. Fix the leak and you can redeploy as often as you want. The leak does not have to be in your code, it could also be in a library or the container. The very latest Tomcat 6 and 7 versions help a lot.