1.Java堆溢出
Java堆用于储存对象实例,我们只要不断地创建对象,并且保证
GC Roots
到对象之间有可达路径来避免垃圾回收机制清除这些对象,那么随着对象数量的增加,总容量触及最大堆的容量限制后就会 产生内存溢出异常。
限制Java
堆的大小为
20MB
,不可扩展(将堆的最小值
-Xms
参数与最大值
-Xmx
参数设置为一样即可避免堆自动扩展),通过参数-XX
:
+HeapDumpOnOutOf-MemoryError
可以让虚拟机 在出现内存溢出异常的时候Dump
出当前的内存堆转储快照以便进行事后分析。
public class HeapOOM {
static class OOMObject {
}
public static void main(String[] args) {
List<OOMObject> list = new ArrayList<OOMObject>();
while (true) {
list.add(new OOMObject());
}
}
}
2.虚拟机栈和本地方法栈溢出
关于虚拟机栈和本地方法栈,在《Java
虚拟机规范》中描述了两种异常:
1
)如果线程请求的栈深度大于虚拟机所允许的最大深度,将抛出
StackOverflowError
异常。
使用没有出口递归的方式,超出虚拟机所允许的最大深度
public class JavaVMStackSOF {
private int stackLength = 1;
public void stackLeak() {
stackLength++;
stackLeak();
}
public static void main(String[] args) throws Throwable {
JavaVMStackSOF oom = new JavaVMStackSOF();
try {
oom.stackLeak();
} catch (Throwable e) {
System.out.println("stack length:" + oom.stackLength);
throw e;
}
}
2
)如果虚拟机的栈内存允许动态扩展,当扩展栈容量无法申请到足够的内存时,将抛出OutOfMemoryError异常。