方法区用于存放Class的相关信息,如类名、访问修饰符、常量池、字段描述、方法描述等。对于这些区域的测试,基本的思路是运行时产生大量的类去填满方法区,直到溢出,用GCLib可以方便我们测试方法区溢出。
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
/**
* VM参数 : -XX:-PermSize=10m -XX:MaxPermSize=10m
* */
public class Main {
public static void main(String[]args) {
while (true) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(OOMObject.class);
enhancer.setUseCache(false);
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
return methodProxy.invokeSuper(o, objects);
}
});
OOMObject oomObject = (OOMObject) enhancer.create();
oomObject.sayHi();
}
}
static class OOMObject{
public void sayHi(){
System.out.println("hi");
}
}
}
运行结果:
Caused by: java.lang.OutOfMemoryError: PermGen space
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClassCond(ClassLoader.java:631)
at java.lang.ClassLoader.defineClass(ClassLoader.java:615)
... 8 more
以上是在JDK1.6下运行的结果,我用1.8则只会循环地输出"hi"而不报错,可能是垃圾回收机制改良了