问:请分别写出一段堆和栈溢出的 Java 代码片段?
答:代码如下。
public class Test {
//堆 溢出例子 OOM
public void heapException() {
for(;;) {
ArrayList list = new ArrayList (2000);
}
}
//栈 溢出例子 SOF
public void stackException() {
count++;
this.stackException();
}
int count = 1;
public static void main(String[] args) {
Test test = new Test();
test.heapException();
test.stackException();
}
}
如上可见,递归调用可以导致栈溢出,不断的创建大对象可以导致堆溢出。
因为
定义一个基本数据类型变量、一个对象的引用、函数调用现场等都是保存在
JVM 中的栈空间。通过 new 关键字和构造器创建的对象一般都放在
堆空间,堆是垃圾收集器管理的主要区域。
问:简单说说 StackOverflowError 与 OutOfMemeryError 的区别?
答:区别如下。
StackOverflowError:
当启动一个新的线程时虚拟机会为其分配一个栈空间,java 栈以帧为单位保存线程运行状态,当线程调用一个方法时 JVM 会压入一个新的栈帧到这个线程的栈空间中,只要这个方法还没返回则这个栈帧就会一直存在。所以如果方法的嵌套调用层次太多(如递归调用),随着栈帧的增加导致总和大于 JVM 设置的 -Xss 值就会抛出 StackOverflowError 异常。
OutOfMemoryError:
OOM 异常会分几种情况出现。
-
堆内存溢出:当需要为对象实例化分配堆内存空间时,而堆的占用已经达到了设置的最大值(通过 -Xmx)就会抛出 OutOfMemoryError 异常。
-
方法区内存溢出:方法区存放 java 类信息(如类名、访问修饰符、常量池、字段描述、方法描述等),在类加载器加载 class 文件到内存时 JVM 会提取类的这些信息放到方法区,而此时如果需要存储这些类信息且方法区的内存占用又已经达到最大值(通过 -XX:MaxPermSize)则会抛出 OutOfMemoryError 异常。
转自公众号《码农每日一题》