2013-04-21 66 views
6

我用Java反射在這樣的代碼:java.lang.OutOfMemoryError:PermGen的空間:Java反射

Method method = LogFactory.class.getDeclaredMethod("getContextClassLoader"); 
method.setAccessible(true); 
ClassLoader classLoader = (ClassLoader)method.invoke(null); 
LogFactory.release(classLoader); 

我用jprofiler可以看到這樣sun.reflect.GeneratedMethodAccessor11

這些類每增加了許多類電話

sun.reflect.BootstrapConstructorAccessorImpl 
sun.reflect.NativeConstructorAccessorImpl 
sun.reflect.DelegatingConstructorAccessorImpl 
sun.reflect.DelegatingClassLoader 

我想這就是爲什麼PermGen空間增加了,如何清理這些類?

+0

爲什麼不創造更多的燙髮空間? – StarPinkER 2013-04-21 10:41:31

+0

也許我應該做更多的測試,我使用eclipse調試代碼和jprofiler附加它。 – Fatkun 2013-04-21 10:45:11

+0

@JermaineXu默認的perm空間是128MB,但它在一個月後達到了 – Fatkun 2013-04-21 10:48:14

回答

10

有一篇相當不錯的文章,討論關於potential native memory use in reflection delegating classloaders

When using Java reflection, the JVM has two methods of accessing the information on the class being reflected. It can use a JNI accessor, or a Java bytecode accessor. If it uses a Java bytecode accessor, then it needs to have its own Java class and classloader (sun/reflect/GeneratedMethodAccessor class and sun/reflect/DelegatingClassLoader). Theses classes and classloaders use native memory. The accessor bytecode can also get JIT compiled, which will increase the native memory use even more. If Java reflection is used frequently, this can add up to a significant amount of native memory use. The JVM will use the JNI accessor first, then after some number of accesses on the same class, will change to use the Java bytecode accessor. This is called inflation, when the JVM changes from the JNI accessor to the bytecode accessor. Fortunately, we can control this with a Java property. The sun.reflect.inflationThreshold property tells the JVM what number of times to use the JNI accessor. If it is set to 0, then the JNI accessors are always used. Since the bytecode accessors use more native memory than the JNI ones, if we are seeing a lot of Java reflection, we will want to use the JNI accessors. To do this, we just need to set the inflationThreshold property to zero.

設置sun.reflect.inflationThreshold 0通過-Dsun.reflect.inflationThreshold=0會做的技巧你。

+1

-Dsun.reflect.inflationThreshold = 0將使所有調用使用GeneratedMethodAccessor(jdk6u51 macosx mountain lion)。將它設置爲一個很大的值(Integer.MAX_VALUE)將會很好。 – 2013-09-25 12:16:47

1

如果你是一個甲骨文JVM那麼只需要設置:

sun.reflect.inflationThreshold=2147483647 

如果您對IBM JVM,那麼你就需要設置:

-Dsun.reflect.inflationThreshold=0 

請注意,兩個JVM在解釋方式上都有所不同。

瞭解更多詳情參考:

inflation_system_properties

native memory use