要模拟出方法区和运行时常量池的溢出,这里需要区分一下JDK的版本。
JDK1.6及之前的版本,常量池是方法区中的一部分,在JDK1.7开始,常量池被放到的heap中。
代码:
import java.util.ArrayList;
import java.util.List;
/**
* www.itzhimei.com
* 编程技术之美-IT之美
*/
public class ConstantPoolOOM {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
int i=0;
while(true) {
String s = "a"+i++;
list.add(s.intern());
}
}
}
JVM参数:
-Xms10M -Xmx10M -XX:PermSize=5M -XX:MaxPermSize=5M
报错如下:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at com.itzhimei.study.jvm.ConstantPoolOOM.main(ConstantPoolOOM.java:12)
Java HotSpot(TM) 64-Bit Server VM warning: ignoring option PermSize=5M; support was removed in 8.0
Java HotSpot(TM) 64-Bit Server VM warning: ignoring option MaxPermSize=5M; support was removed in 8.0
重点在这里:java.lang.OutOfMemoryError: Java heap space
报错是提示heap内存不足,因为我本地是JDK1.8
如果是JDK1.6或以下,则会提示java.lang.OutOfMemoryError:PermGen space,那么就表示方法区溢出了,有兴趣的可以用1.6试一试。
在JDK1.7及以后的版本中要让PermGen space内存溢出,那么需要使用类似spring的CGLIB这样的功能,在运行时动态生成大量class,编译成字节码,加载到JVM的方法区中,因为class字节码都是存放在方法区的,当动态生成的class过多,那么方法区自然就溢出了。
内容学习自周志明老师的《深入理解Java虚拟机》