引言: 在JVM中, PermSpace主要存放什么信息?如何去理解它的溢出呢?
什么是PermSpace?
PermSpace主要是存放静态的类信息和方法信息,静态的方法和变量,final标注的常量信息等。
PermSpace溢出的Case 1:
这里的JDK版本1.6.0_45(jdk7/jdk8不存在类似问题)
Opertion System: Ubuntu 14.04
JVM 参数: -Xmx128m -Xms64m -XX:PermSize=5m -XX:MaxPermSize=10M
利用的原理:在java中,String类型的常量字符串信息会被存放到PermSpace区域中,形成常量池; 同时其并不会被GC进行回收,故此利用循环创建常量信息来达到PermSpace溢出的目的。
import java.util.ArrayList; import java.util.List; public class PermSpaceStringConstant { public static void main(String[] args) { List<String> strs = new ArrayList<String>(); int i = 0; while(true) { strs.add(String.valueOf(i++).intern()); System.out.println("We have created " + i + " constant String."); } } }运行结果:
PermSpace溢出的Case 2:
JVM: jdk1.6.0_45, Operation System: Ubuntu 14.04
JVM 参数: -Xmx128m -Xms64m -XX:PermSize=5m -XX:MaxPermSize=5M
第三方类库: cglib-nodep-3.1.jar
利用的原理: PermSpace存放类的信息,故此利用cglib动态创建新的类,利用循环创建足够多的类信息,充满PermSpace区域,从而达到溢出PermSpace的目的。
源代码如下:
import java.lang.reflect.Method; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; public class CGLibTest { public static void main(String[] args) { new CGLibTest().testCGLIB(); } public void testCGLIB() { int i = 0; while(true) { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(EnhancerTest.class); enhancer.setCallback(new MethodInterceptorImpl()); EnhancerTest demo = (EnhancerTest) enhancer.create(); //demo.test(); //System.out.println(demo); System.out.println("Create " + (i++) +" instance:" + demo.getClass().getSimpleName()); } } static class EnhancerTest { } private static class MethodInterceptorImpl implements MethodInterceptor { @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { //System.err.println("Before invoke " + method); Object result = proxy.invokeSuper(obj, args); //System.err.println("After invoke" + method); return result; } } }
运行结果:
总结:
通过以上2个Cases来分析,可以更加深刻的了解PermSpace所存放的信息内容了:类信息和常量静态的信息。