java.lang.OutOfMemoryError: PermGen space on web app usage

8.9k views Asked by At

I am struggling with an outOfMemory PermGen issue that has been showing up recently. One of the log snippets that was saved when error appeared:

java.lang.OutOfMemoryError: PermGen space
        at java.lang.ClassLoader.defineClass1(Native Method)
        at java.lang.ClassLoader.defineClassCond(ClassLoader.java:632)
        at java.lang.ClassLoader.defineClass(ClassLoader.java:616)
        at org.apache.felix.framework.ModuleImpl$ModuleClassLoader.findClass(ModuleImpl.java:1872)
        at org.apache.felix.framework.ModuleImpl.findClassOrResourceByDelegation(ModuleImpl.java:720)
        at org.apache.felix.framework.ModuleImpl.access$300(ModuleImpl.java:73)
        at org.apache.felix.framework.ModuleImpl$ModuleClassLoader.loadClass(ModuleImpl.java:1733)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:248)

I've increased max perm size -XX:MaxPermGen=128m but this is just a temporary solution because I am preety sure we are facing some memory leak here. The web part of our applications is deployed on jetty (jsf + icefaces). Clicking on random components increases the memory used - I am monitoring it with jstat -gcold and nearly every hit means 3-4kb more. I've added -XX:+TraceClassLoading to the jvm params and see many sun.reflect.GeneratedConstructorAccessor and sun.reflect.GeneratedMethodAccessor being logged when there is any action on the web user interface. I also made a heap dump when 99% of permgen was used. I used YourKit profiler to analyze the heap. In the class loader tab there are loaads of sun.reflect.DelegatingClassLoader rows with 1 class for each. What might be causing the memory to constantly grow? Any help will be really appreciated.

thanks in advance, Lukasz

5

There are 5 answers

1
jwenting On

Permgen problems are usually caused by some process doing a LOT of String.intern() operations. Some XML/HTML generators and parsers are guilty of this. Look there first, you may hit on the culprit quickly.

1
Grzegorz Oledzki On

I would suggest using Eclipse MAT and to follow this tutorial dedicated to permgen problems.

Although as duffymo noticed you've done a great job analyzing the problem, the very origin of the problems seems still unknown. Maybe it's just one of the components, some parser (as jwenting suggests) or similar. The problem doesn't necessarily mean you need to throw away JSF from the stack.

4
BalusC On

First of all, this is not specifically related to JSF. You're simply giving your appserver too little memory as compared to the needs of your webapp. You would have the same problem with every other framework which uses under the covers a good shot of reflection (think of all those EL resolvings). This can be JSF, Wicket, Spring-MVC and even plain JSP/Servlet. The chance is only bigger on component based web frameworks which rely heavily on EL resolvers, such as JSF (and others).

Further it's known that Tomcat (-based) servers may cause this as well when you (hot)redeploy a bit too often. Get yourself through the following links to learn about it and how to deal with it:

3
duffymo On

First of all, kudos to you for doing such a thorough job of investigating this and an even better job of writing your question. The world (and this site) would be a better place if everyone was as talented and as good a writer as you are.

I think you've already found the answer: I think JSF and its use of reflection is your problem.

This is one reason why I avoid JSF like the plague.

In my opinion, JSF is a failed extension of Struts. I'd consider an HTML/CSS/JavaScript/AJAX UI to be as capable as JSF, if not more so, and far less taxing on my JVM. The UI calls services and stays nice and separate from the server side.

0
Nat On

On the Sun JVM, reflective access to properties and methods is initially performed by calling through JNI into the JVM implementation. If the JVM notices that a method or field is being accessed by reflection a lot, it will generate bytecode to do the same thing -- a mechanism that it calls "inflation". This has an initial speed hit, but after that runs about 20 times faster. A big win if you do a lot of reflection.

That bytecode lives in classes created by DelegatingClassLoader instances and take up permgen space. If it is a problem, you can turn inflation off by setting the system property sun.reflect.inflationThreshold to 0 (zero).