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

Lukasz picture Lukasz · Feb 21, 2011 · Viewed 8.7k times · Source

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

Answer

Nat picture Nat · Jan 9, 2012

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