在《java虚拟机规范》规范中,对本地方法栈和虚拟机栈的使用中规定了两个异常:stackoverflowerror与outofmemoryerror,那么,这种异常有什么区别呢?
无论是本地方法栈,还是虚拟机栈,都是线程私有的,当一个线程启动的时候,jvm就会给这个线程分配一个栈,然后每当你调用一个方法的时候,jvm就会往这个栈压入一个栈帧,方法调用完毕,栈帧出栈。注意,一个栈能容纳的栈帧是固定的,有默认的值,当然你也可以通过-Xss去调。但这个栈里面的引用所指向堆内存空间是可以扩展的。简而言之,一个栈的栈帧数目是确定的,而与该栈相关联的堆内存是可以动态扩展的,这些是前提。
1.stackoverflowerror
前面说到,当一个线程启动的时候,jvm就会给这个线程分配一个栈,随着程序的执行,会不断执行方法,因此栈帧会不断入栈和出栈。然后,一个栈所能容纳的栈帧是有限的,当栈帧的数量超过了栈所允许的范围的时候(比如递归调用),就会抛出stackoverflowerror异常。下面以一段代码演示:
public class Test {
public void recursion() {
recursion();
}
public static void main(String[] args) {
Test test = new Test();
test.recursion();
}
}
2.outofmemoryerror
程序在执行的过程中,需要不断的在堆内存new对象,每new一个对象,就会占用一段内存,当对没有足够的内容分配给对象示例时,就会抛出outofmemoryerror异常。演示代码如下:
public class Test {
public static void main(String[] args) {
ArrayList<Test> list = new ArrayList<Test>();
while (true) {
list.add(new Test());
}
}
}