7

次のようなコードで 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スペースが増加する理由だと思います.これらのクラスをきれいにする方法は?

4

2 に答える 2

12

リフレクション委譲クラスローダーでの潜在的なネイティブメモリの使用について議論しているかなり良い記事があります。

Java リフレクションを使用する場合、JVM には、リフレクションされるクラスの情報にアクセスする 2 つの方法があります。JNI アクセサーまたは Java バイトコード アクセサーを使用できます。Java バイトコード アクセサーを使用する場合は、独自の Java クラスとクラスローダー (sun/reflect/GeneratedMethodAccessor クラスと sun/reflect/DelegatingClassLoader) が必要です。これらのクラスとクラスローダーはネイティブ メモリを使用します。アクセサー バイトコードは JIT コンパイルも取得できるため、ネイティブ メモリの使用量がさらに増加し​​ます。Java リフレクションが頻繁に使用されると、ネイティブ メモリの使用量が大幅に増加する可能性があります。JVM は最初に JNI アクセサーを使用し、次に同じクラスに何度かアクセスした後、Java バイトコード アクセサーを使用するように変更します。これは、JVM が JNI アクセサーからバイトコード アクセサーに変わるとき、インフレーションと呼ばれます。幸運、これは Java プロパティで制御できます。sun.reflect.inflationThreshold プロパティは、JNI アクセサーを使用する回数を JVM に通知します。0 に設定すると、JNI アクセサーが常に使用されます。バイトコード アクセサーは JNI アクセサーより多くのネイティブ メモリを使用するため、多くの Java リフレクションが見られる場合は、JNI アクセサーを使用する必要があります。これを行うには、inflationThreshold プロパティをゼロに設定するだけです。

Oracle JVM を使用している場合は、次の設定のみが必要です。

-Dsun.reflect.inflationThreshold=2147483647

IBM JVM を使用している場合は、次のように設定する必要があります。

-Dsun.reflect.inflationThreshold=0

両方の JVM は解釈方法が異なることに注意してください。

于 2013-04-21T12:02:29.430 に答える