JVM实战 OutOfMemoryError 方法区和运行时常量池溢出

要模拟出方法区和运行时常量池的溢出,这里需要区分一下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虚拟机》