I use java reflection in the code like this:
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
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?
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. 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
to 0 by -Dsun.reflect.inflationThreshold=0
will do the tricks for you.
If you are on a Oracle JVM then you would only need to set:
sun.reflect.inflationThreshold=2147483647
If you are on IBM JVM, then you would need to set:
-Dsun.reflect.inflationThreshold=0
Please note that both JVMs differ in the way they interpret.
Reference for more details:
inflation_system_properties
native memory use