2013-04-21 20 views
6

Io uso java riflessione nel codice come questo:java.lang.OutOfMemoryError: PermGen spazio: java riflessione

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

Io uso jprofiler possono vedere molti di classe come questo sun.reflect.GeneratedMethodAccessor11

queste classi sono aumentate per chiama

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

Penso che questo sia il motivo per cui aumenta lo spazio PermGen, come pulire queste classi?

+0

Perché non creare più spazio permanente? – StarPinkER

+0

Forse dovrei fare più test, uso eclipse per il debug del codice e jprofiler per collegarlo. – Fatkun

+0

@JermaineXu lo spazio perm predefinito è 128MB, ma raggiunge dopo un mese – Fatkun

risposta

10

C'è un articolo molto carino che parla di 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.

Set sun.reflect.inflationThreshold-0 da -Dsun.reflect.inflationThreshold=0 farà i trucchi per voi.

+1

-Dsun.reflect.inflationThreshold = 0 farà invocare tutto per usare GeneratedMethodAccessor (jdk6u51 macosx mountain lion). impostarlo su un valore elevato (Integer.MAX_VALUE) andrà bene. –

1

Se siete su un Oracle JVM allora si avrebbe solo bisogno di impostare:

sun.reflect.inflationThreshold=2147483647 

Se siete su IBM JVM, allora si avrebbe bisogno di impostare:

-Dsun.reflect.inflationThreshold=0 

prega di notare che entrambe le JVM differiscono nel modo in cui interpretano.

di riferimento per maggiori dettagli:

inflation_system_properties

native memory use

Problemi correlati