You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

全局创建对象触发StackOverflowError而非OutOfMemoryError?附代码疑问

关于Java栈溢出与堆溢出的两个问题解答

问题1:全局创建对象时出现StackOverflowError,为何未触发OutOfMemoryError?

首先得把两个错误的本质掰明白:

  • StackOverflowError:是栈内存耗尽引发的,常见场景是方法调用层级过深(比如无限递归),或者实例初始化时陷入无限递归创建对象的死循环。
  • OutOfMemoryError(堆内存版):是堆内存无法再分配新对象时才会触发的错误。

当你在全局(比如类的实例变量里直接new自身)创建对象时,会陷入「创建对象→初始化实例变量→再创建对象→再初始化实例变量」的无限递归链。这个过程中,每一次对象初始化都会触发方法调用(比如构造器、实例变量初始化逻辑),而每一次方法调用都会在栈中生成一个新的栈帧。

栈的容量通常远小于堆(栈一般是MB级,堆动辄GB级),所以栈会先被撑爆,直接触发StackOverflowError让程序终止——这时候堆还没来得及积累足够多的对象,自然没机会触发OutOfMemoryError。

问题2:给定代码为何未出现OutOfMemoryError?

先把代码贴出来方便分析:

public class Abc {
    Abc abc1=new Abc();
    static Abc abc=new Abc();
    public static void main(String[] args) {
        Abc abc=new Abc();
    }
}

咱们一步步拆解执行流程,你就懂了:

  1. JVM启动后要执行main方法,首先得加载Abc类。类加载时会初始化静态成员变量abc,也就是执行new Abc()。
  2. 执行new Abc()创建实例时,会先初始化非静态成员变量abc1,也就是又调用new Abc()。
  3. 这个新的Abc实例创建时,又要初始化它自己的abc1,再次执行new Abc()……这就形成了无限递归的初始化循环。

和第一个问题的核心逻辑一致:每一次初始化操作都会在栈中压入新的栈帧,栈的小容量扛不住这种无限递归,很快就会触发StackOverflowError,程序直接崩溃。堆内存还没来得及分配足够多的对象(甚至可能只创建了几个实例),所以根本到不了触发OutOfMemoryError的地步。

内容的提问来源于stack exchange,提问作者user9558710

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 04:34:04