Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JBoss 7, java.lang.OutOfMemoryError: PermGen space

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)?

like image 296
MaVRoSCy Avatar asked Jul 25 '12 09:07

MaVRoSCy


People also ask

How do I increase my PermGen space?

To fix it, increase the PermGen memory settings by using the following Java VM options. -XX:PermSize<size> - Set initial PermGen Size. -XX:MaxPermSize<size> - Set the maximum PermGen Size. In the next step, we will show you how to set the VM options in Tomcat, under Windows and Linux environment.

What causes PermGen space error?

lang. OutOfMemoryError: PermGen Space is a runtime error in Java which occurs when the permanent generation (PermGen) area in memory is exhausted. The PermGen area of the Java heap is used to store metadata such as class declarations, methods and object arrays.

How do I set PermGen space in eclipse?

Open eclipse. ini file, it is located in root eclipse directory. there you can change -Xms and -Xmx parameter to change permgen size. There you can change -XX:PermSize and -XX:MaxPermSize.

How do I increase PermGen space in Weblogic?

To set PermGen size you can use e.g. -XX:PermSize=512m -XX:MaxPermSize=512m . Regarding Weblogic, set the JAVA_OPTIONS and see if these options are properly passed in as parameters into your Java process. You can also directly set these parameters in the startWeblogic.


4 Answers

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.

like image 196
Craig Ringer Avatar answered Oct 03 '22 22:10

Craig Ringer


The VM parameter is:

-XX:MaxPermSize=256M

Just make it large enough that you don't hit the limit.

Broadly speaking, perm gen memory is used for objects associated with Classes and interned Strings. You shouldn't run out unless you have use lot of different classes.

like image 44
Bohemian Avatar answered Oct 03 '22 21:10

Bohemian


We had to do the exact same thing and unfortunately visualvm did not do much for us.

We ended up using eclipse mat to analyse the heap dump generated on crash and then checked out the leak suspects report which told us that there were a lot of ModuleClassLoader instances being leaked.

Clicking on one of the instances in the overview tab and then selecting merge shortest paths to GC roots + exclude weak references gave us our culprit which was not allowing these ModuleClassLoader instances to be GC'ed!

https://smalldata.tech/blog/2015/09/29/detecting-java-permgen-memory-leak

like image 28
Victor Parmar Avatar answered Oct 03 '22 22:10

Victor Parmar


Why it happens?

The "PermGen" error happens, when the Java virtual machine runs out of memory in the permanent generation. Recall that Java has a generational garbage collector, with four generations: eden, young, old and permanent. In the eden generation, objects are very short lived and garbage collection is swift and often. The young generation consists of objects that survived the eden generation (or was pushed down to young because the eden generation was full at the time of allocation), garbage collection in the young generation is less frequent but still happens at quite regular intervals (provided that your application actually does something and allocates objects every now and then). The old generation, well, you figured it. It contains objects that survived the young generation, or have been pushed down, and garbage collection is even less infrequent but can still happen. And finally, the permanent generation. This is for objects that the virtual machine has decided to endorse with eternal life - which is precicely the core of the problem. Objects in the permanent generation are never garbage collected; that is, under normal circumstances when the jvm is started with normal command line parameters. So what happens when you redeploy your web application is, that your WAR file is unpacked and its class files loaded into the jvm. And here's the thing: almost always ends up in the permanent generation... (taken from: http://rlogiacco.blogspot.com/2009/02/jboss-and-permgen-outofmemoryerror.html)

Here are some advices :

use this parameters for your JVM. they tell the Garbage Collector to invoke its algorithm also on the PermGen.

set JAVA_OPTS=-Xms512m -Xmx1024m 
-XX:PermSize=512m 
-XX:MaxPermSize=1024m 
-XX:+UseConcMarkSweepGC 
-XX:+CMSPermGenSweepingEnabled 
-XX:+CMSClassUnloadingEnabled 
  • The CMSPermGenSweepingEnabled setting includes the PermGen in a garbage collection run. By default, the PermGen space is never included in garbage collection (and thus grows without bounds).
  • The CMSClassUnloadingEnabled setting tells the PermGen garbage collection sweep to take action on class objects. By default, class objects get an exemption, even when the PermGen space is being visited during a garabage collection.

Restart your JBOSS because each time you deploy application, you increase the amount of data in the PermGen.

You can also use JRocket JVM instead of the Sun JVM. it doesn't have any PermGen in its Garbage Collector algorithm.

like image 27
Kamal SABBAR Avatar answered Oct 03 '22 21:10

Kamal SABBAR