简体   繁体   English

java.lang.OutOfMemoryError:PermGen space:java reflection

[英]java.lang.OutOfMemoryError: PermGen space: java reflection

I use java reflection in the code like this: 我在代码中使用java反射,如下所示:

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

I use jprofiler can see many class like this sun.reflect.GeneratedMethodAccessor11 我用jprofiler可以看到很多这样的类sun.reflect.GeneratedMethodAccessor11

these classes are increased per call 这些课程每次通话都会增加

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

I think this is why PermGen space increase, how to clean these classes? 我想这就是为什么PermGen空间增加,如何清理这些类?

There is a pretty nice article discussing about 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. 使用Java反射时,JVM有两种方法可以访问正在反映的类的信息。 It can use a JNI accessor, or a Java bytecode accessor. 它可以使用JNI访问器或Java字节码访问器。 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). 如果它使用Java字节码访问器,那么它需要有自己的Java类和类加载器(sun / reflect / GeneratedMethodAccessor类和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. 访问器字节码也可以进行JIT编译,这将进一步增加本机​​内存的使用。 If Java reflection is used frequently, this can add up to a significant amount of native memory use. 如果经常使用Java反射,这可能会增加大量的本机内存使用。 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. JVM将首先使用JNI访问器,然后在同一个类上进行一些访问后,将更改为使用Java字节码访问器。 This is called inflation, when the JVM changes from the JNI accessor to the bytecode accessor. 当JVM从JNI访问器更改为字节码访问器时,这称为通胀。 Fortunately, we can control this with a Java property. 幸运的是,我们可以使用Java属性来控制它。 The sun.reflect.inflationThreshold property tells the JVM what number of times to use the JNI accessor. sun.reflect.inflationThreshold属性告诉JVM使用JNI访问器的次数。 If it is set to 0, then the JNI accessors are always used. 如果设置为0,则始终使用JNI访问器。 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. 由于字节码访问器使用比JNI更多的本机内存,如果我们看到很多Java反射,我们将需要使用JNI访问器。 To do this, we just need to set the inflationThreshold property to zero. 为此,我们只需要将inflationThreshold属性设置为零。

Set sun.reflect.inflationThreshold to 0 by -Dsun.reflect.inflationThreshold=0 will do the tricks for you. 设置sun.reflect.inflationThreshold 0由-Dsun.reflect.inflationThreshold=0将做把戏给你。

If you are on a Oracle JVM then you would only need to set: 如果您使用的是Oracle JVM,那么您只需要设置:

sun.reflect.inflationThreshold=2147483647 

If you are on IBM JVM, then you would need to set: 如果您使用的是IBM JVM,那么您需要设置:

-Dsun.reflect.inflationThreshold=0

Please note that both JVMs differ in the way they interpret. 请注意,两个JVM的解释方式不同。

Reference for more details: 参考更多细节:

inflation_system_properties inflation_system_properties

native memory use 本机内存使用

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM