jvm 的out of memory常见类型及演示demo
说起jvm就避免不了谈及jvm的内存划分。本文主要说一下hotspot运行时数据区域的的划分和常见的Out Of Memory演示demo。本文主旨在记录自己所学知识,同时方便后续查阅,有不足支出请大家指正。
一、hotspot的内存分区
hotspot的jvm运行时数据区域分为堆、栈、方法区(永久代)、程序计数器。
二、各分区的简要介绍
堆
堆又细分为新生代和老年代。新生代又细分为Eden空间、from survivor空间和to survivor空间,其中Eden:survivor=8:1(默认情况)。可以通过-Xms10m和-Xmx20m来设置堆内存的大小。可以通过-XX:NewSize=10m和-XX:MaxNewSize=20m来设置新生代的大小。可以通过-XX:NewRatio=2(老年代是新生代大小的2倍)来设置老年代和新生代的比例,通过-XX:SurvivorRatio=8来设置Eden和survivor的比例。
堆上会抛Out Of Memory异常的demo
//package OutOfMemory;//注释掉 import java.util.ArrayList; public class JavaHeapSpace { public static void main(String args[]){ ArrayList arryList=new ArrayList(); int i=0; while(true){ i++; arryList.add(String.valueOf(i)); if(i<0){ break; } } } }
其中包名我是注释掉的,因为我是在cmd进行编译和运行。若加上包名会报找不到主函数的异常,执行结果如下:
栈
栈又分成虚拟机栈和本地方法栈,可以通过-xss10m来设置线程栈的大小
栈异常之*Error
//package OutOfMemory;//注释掉 import java.util.ArrayList; public class JavaHeapSpace { public static void main(String args[]){ ArrayList arryList=new ArrayList(); int i=0; while(true){ i++; arryList.add(String.valueOf(i)); if(i<0){ break; } } } }
栈异常之 unable to create native thread
package OutOfMemory; public class ThreadStack { public void notStop(){ while(true){ } } public void threadStack(){ while(true) { Thread t = new Thread(new Runnable() { @Override public void run() { notStop(); } }); t.start(); } } public static void main(String args[]){ ThreadStack threadStack=new ThreadStack(); threadStack.threadStack(); } }
以上是常见的两种栈溢出异常。
方法区(永久代)
方法区(永久代)可以通过调整-XX:PermSize=10m和-XX:MaxPermSize=10m来设置方法区的大小,不过此区域有最小默认值。即想调整方法区比较小时,不一定生效。如下案例代码在jdk1.6下是可以出现异常的,在jdk1.7及以上不会出现异常
//package OutOfMemory; import java.util.ArrayList; public class PermGenSpace { public static void main (String args[]){ ArrayList arryList=new ArrayList(); int i=0; while(true){ arryList.add(String.valueOf(++i).intern()); } } }
最后一个是程序计数器,此区域是不会出现OutOfMemoryError的。