书中介绍JVM内存区域的时候,曾经讲过,除了程序计数器以外,虚拟机内存的其他几个运行时数据区域都有可能发生OutOfMemoryError(简称OOM)的可能。但是程序实际运行过程中,每个区域的异常内容又稍微有着一点点的差异,本文试图归纳可能出现的几种错误日志,以方便日后可以大致地判断可能发生OOM的区域。第一种是java堆溢出异常
模拟java对异常出现的场景很简单。因为堆是用来保存对象的,所以只要不停地创建对象,迟早堆内迟早是会满的 ,例如下面这种代码:List list = new ArrayList;while(true){list.add(new Object);}
这种堆异常会报出来java.lang.OutOfMemoryError: Java heap space
主要是这个java heap space,可以直接定位到堆异常第二种是虚拟机栈和本地方法栈异常
栈中有两种异常一种是线程请求的栈深度大于虚拟机所允许的最大深度 ,这时会抛出StackOverFlowError另一种是在允许动态扩展的栈内存中,当扩展的栈容量无法申请到足够内存的时候,会抛出OutOfMemoryError异常
但是第二种情况一般不会出现,因为现在的HotSpot虚拟机不支持动态扩展内存,所以除非创建线程的时候内存就不足,否则不会出现第二种异常。
对于第一种异常 ,实验方法也简单,创建大量的实例变量,直到堆满栈内存时,会看到报出来
Exception in thread "main" java.lang.StackOverflowError这个错第三种是方法区和运行时常量池溢出
常量池溢出好搞,一直不停地创建常量,并且保持引用Set set = new HashSet;long x = 0;while(true){set.add(String.valueOf(i++).intern);}
一会就能看到报错,不过要注意这个异常JDK版本不同的话具体内容也是不一样的
JDK7之前是以下异常内容:
Excpetion in thread "main" java.lang.OutOfMemoryError: PernGen space
到了JDK7开始就变成了java.lang.OutOfMemoryError: Java heap space
因为JDK7开始常量池就被移到堆空间里去了