JBoss 7, java.lang.OutOfMemoryError: PermGen space

MaVRoSCy picture MaVRoSCy · Jul 25, 2012 · Viewed 41.2k times · Source

I've hit this error where the CPU usage goes to its limits and JBoss needs a restart (java.lang.OutOfMemoryError: PermGen space).

I found a solution for older JBoss version to increase the MaxPermSize. I guess the same goes for JBoss7.

Which value would be good enough in order not to face any problem again? Is there any way to get permanently away from this problem (like lets say use a different VM like JRockit)?

Answer

Craig Ringer picture Craig Ringer · Jul 31, 2012

Since this happens after multiple redeploys it sounds like you've encountered a classloader leak, a common kind of permgen leak.

These lovely beasts happen because of normal (non-weak) references from objects owned by the container to objects that're instances of classes loaded from the application classloader. If those references aren't cleared on undeploy there's still a strong reference chain to the application's classloader, so it can't be GC'd and the loaded classes can't be freed.

A common cause is static collections in container classes that have non-static references to application classes added.

JBoss AS 7 has some fairly strong provisions in its module system to prevent classloader leaks, so I'm surprised you've managed to trigger one. I haven't seen a classloader leak since I moved to AS7 from Glassfish.

Increasing MaxPermSize will buy you some time, but it won't get rid of the problem.

You really need to work out why the classloader is leaking. Doing this is "fun". You enjoy taxes, intermittent faults, and cleaning the shower, right? See the links in the first par for some blogs that'll get you started on tracking the leak down. Basically, you'll want to use VisualVM and OQL to dig for references to your app classloader, or take a heap dump and use jhat (part of the JDK) to find the references. Either way, the idea is to figure out where the strong reference chain from the app server to your classloader via instances of your app classes is.

Alternately, it can help to take a copy of your app then start ripping bits out of it until the leak goes away. You can tell if it's leaking by connecting VisualVM or other monitoring to the app server VM and watching to see if PermGen increases after two or more deploy/undeploy cycles. Consider automating the deploy/undeploy cycles. Narrow down the cause of the leak to a small part of your app and/or one of its dependencies and produce a small, self-contained test case, then submit that as a bug report on (a) JBoss AS 7, since AFAIK it's meant to stop this happening and (b) the culprit that's holding the reference.

If you narrow the cause down to a dependency that's bundled inside your deployment archive, moving it into a JBoss AS 7 module may take care of the problem. Create a JBoss module for it, deploy it to the modules directory of AS7, and add a dependency on it to your deployment via your Manifest.MF or via a jboss-deployment-structure.xml. See the documentation on the AS7 class loader.

This is why the fact that Project Jigsaw has been deferred makes me sad. Java needs a strong module system that gets rid of this crud.