2016-12-16 26 views
0

私は(意図的に)を生成し、次のコードを持っているPermGen java.lang.OutOfMemoryErrorPermGenのフラグ期待どおりに動作しません:-XX:+ CMSClassUnloadingEnabledと-XX:+ CMSPermGenSweepingEnabled


public class Main { 

    public static void main(String[] args) throws InstantiationException, IllegalAccessException, InterruptedException { 
     String name = "MyClass"; 
     DynamicClassLoader cl = new DynamicClassLoader(); 

     int i = 0; 
     while (true) { 
      //code for generating the binary for a class to be loaded. 
      ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES); 
      cw.visit(Opcodes.V1_7, Opcodes.ACC_PUBLIC, name + ++i, null, "java/lang/Object", null); 
      MethodVisitor con = cw.visitMethod(Opcodes.ACC_PUBLIC, "", "()V", null, null); 
      con.visitCode(); 
      con.visitVarInsn(Opcodes.ALOAD, 0); 
      con.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "", "()V", false); 
      con.visitInsn(Opcodes.RETURN); 
      con.visitMaxs(1, 1); 
      cw.visitEnd(); 
      //binary code for class successfully generated 

      Class clazz = cl.defineClass(name + i, cw.toByteArray()); 
      Object o = clazz.newInstance(); 
      System.out.println(o.getClass().getName()); 
     } 
    } 

    private static class DynamicClassLoader extends ClassLoader { 
     public Class defineClass(String name, byte[] b) { 
      return defineClass(name, b, 0, b.length); 
     } 
    } 
} 

私は、Java 7でこのコードを実行します期待どおりに、それはjava.lang.OutOfMemoryError: PermGen spaceエラーを取得します。 私は次のように述べたフラグでこのプログラムを実行しようとすると:

java -XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled -jar target/permgen.jar 

を、私はまだ私は、フラグなしでそれを実行したときとまったく同じポイントで、同じエラーを取得します。 私は、これらのフラグを設定すると、PermGenのリフレッシュが起こらない場合、少なくとも部分的な改善が見られると思いました。しかし、そうではありません。

質問:これらのフラグの意味を誤解していますか?その場合は詳細を教えてください。さもなければ、提案はありますか?

N.B. java -versionの出力は次のとおりです。

Javaのバージョン "1.7.0_95"

OpenJDKのランタイム環境(IcedTeaの2.6.4)(7u95-2.6.4-3)

OpenJDKの64ビットサーバーVM (ビルド24.95-b01、混合モード)

+2

テストケースを変更して、「DynamicClassLoader」のインスタンスがテスト期間全体にわたって保持されないようにすることはできますか? AFAIK、すべてのクラスローダーは、ロードするすべてのクラスへの参照を保持します。あなたのクラスローダがGCされない限り、あなたのクラスはGCできません。おかげさまで、 – omajid

+0

あなたは爪を打つ。 :)。それを受け入れるために応答として投稿してください。 – artaxerxe

答えて

1

すべてのクラスローダーは、ロードするすべてのクラスを強力に参照します。あなたの例では、DynamicClassLoaderの単一インスタンスを再利用し続けます。このクラスローダーは、ロードするすべてのクラスへの強い参照を保持します。ガベージコレクタは、参照できないオブジェクトを決して収集できません。

別のクラスローダーを使用するようにテストケースを変更した場合、ガベージコレクタは、クラスが使用されていないことを識別できる必要があり、メモリを再利用する必要があります。

関連する問題