【发布时间】:2016-12-16 12:05:58
【问题描述】:
我有以下代码(有意)生成 PermGen java.lang.OutOfMemoryError:
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 的完全刷新,至少会看到部分改进。但事实并非如此。
问题:我是否误解了这些标志的含义?如果是这种情况,您能详细说明一下吗?否则,有什么建议吗?
注意java -version 的输出是:
java 版本“1.7.0_95”
OpenJDK 运行时环境 (IcedTea 2.6.4) (7u95-2.6.4-3)
OpenJDK 64 位服务器 VM(内部版本 24.95-b01,混合模式)
【问题讨论】:
-
您能否修改您的测试用例,使您的
DynamicClassLoader实例不会在整个测试期间保留? AFAIK,所有类加载器都保留对它们加载的所有类的引用。除非你的类加载器被 GC'ed,否则你的类不能被 GC'ed。 -
@omajid 谢谢。你一针见血。 :)。请将其作为回复发布以接受它。
标签: java out-of-memory java-7 openjdk permgen