2016-12-16 55 views
0

我有以下代码生成(有意地)一个PermGen的java.lang.OutOfMemoryError标志为PermGen的工作不正常:-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的运行时环境(2.6.4的IcedTea)(7u95-2.6.4-3)

OpenJDK的64位服务器VM (构建24.95-b01,混合模式)

+2

你能否修改你的测试用例,使你的'DynamicClassLoader'实例在整个测试持续时间内都保持不变? AFAIK,所有类加载器保留对它们加载的所有类的引用。除非你的类加载器被GC化了,否则你的类不能被GC化。 – omajid

+0

@omajid谢谢。你打了指甲。 :)。请将其作为回复发布,以便接受它。 – artaxerxe

回答

1

所有类加载器都会强烈引用它们加载的所有类。在你的例子中,你不断重复使用DynamicClassLoader的单个实例。这个类加载器保持对你加载的所有类的强引用。因此垃圾收集器从不会看到它可以收集的未引用的对象。

如果您修改测试用例以使用单独的类加载器,那么垃圾收集器应该能够识别您的类未被使用并且应该回收内存。

相关问题