我有这段代码动态生成并加载类
import javassist.CannotCompileException;
import javassist.ClassPool;
public class PermGenLeak {
private static final String PACKAGE_NAME = "com.jigarjoshi.permgenleak.";
public static void main(String[] args) throws CannotCompileException, InterruptedException {
for (int i = 0; i < Integer.MAX_VALUE; i++) {
ClassPool pool = ClassPool.getDefault();
pool.makeClass(PACKAGE_NAME + i).toClass();
Thread.sleep(3);
}
}
}
我针对Java7 (jdk1.7.0_60)启动了这个类,如预期的那样填满了PermGenSpace,而堆保持未使用状态。
图像显示随时间变化的permgen使用情况,最后JVM被终止。
现在同样的代码运行在Java8 (jdk1.8.0_40-ea)上,如预期的那样不断扩展本地内存(Metaspace),但令人惊讶的是,为了1g的Metaspace,它在OldGen中消耗了3g的Heap(几乎是维持Metaspace的3倍)。
图像显示随时间变化的Metaspace使用情况和系统内存使用情况示例。
Jon Masamitsu的这封电子邮件和这个JEP票据说:
interned
String
和Class stats以及一些其他数据已经被移动到Heap中。
是什么导致这个堆增加,当它把更多的类加载到Metaspace中?