Java 堆栈 以及 SOF 和 OOM 的两个面试小问题

本文通过具体的Java代码示例,深入解析了堆溢出和栈溢出的现象及原因。详细介绍了通过不断创建大对象导致堆空间耗尽引发的OutOfMemoryError,以及通过无限递归调用导致栈空间耗尽引发的StackOverflowError。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问:请分别写出一段堆和栈溢出的 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 异常。

转自公众号《码农每日一题》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值