Java 最深调用栈有多大

Java 最深调用栈有多大

Java 方法调用栈的最大深度并没有固定的值,它主要取决于以下因素:

  1. JVM 实现:不同的 JVM(如 HotSpot、OpenJ9)对栈的管理有所不同,因此最大栈深度可能不同。
  2. 栈大小(Stack Size):可以通过 JVM 选项 -Xss 设置线程的栈大小,栈越大,递归或深层方法调用可以执行得更深。
  3. 方法的局部变量:方法中的局部变量越多,占用的栈空间越大,能支持的最大调用深度就越小。
  4. 64 位 vs. 32 位 JVM:64 位 JVM 一般需要更多的栈空间,因此相同 -Xss 值下,最大调用深度可能低于 32 位 JVM。

JVM 内存区域分为,方法区,堆,虚拟机栈,本地方法栈,程序计数器,而线程调用的栈都存放在虚拟机栈这个区域,每个线程产生的方法栈的总的大小由 JVM 参数 -Xss<size> 控制,默认为 1M,例如 -Xss256k-Xss1m,这个值的大小将影响线程的最大调用深度。
例如 java -Xss512k MyApp,这样,当我们启动 MyApp 的时候,每一个每个线程的 Java 方法调用栈大小设为 512 KB

实测 Java 方法调用栈最大深度

可以通过递归测试 Java 方法调用栈的最大深度:

public class StackDepthTest {
    private static int depth = 0;

    public static void recursive() {
        depth++;
        recursive();
    }

    public static void main(String[] args) {
        try {
            recursive();
        } catch (StackOverflowError e) {
            System.out.println("Stack depth: " + depth);
        }
    }
}

示例测试结果

不同 -Xss 值下的调用深度(大致估算):

JVM 配置 64 位 32 位
-Xss256k ~1,800 ~2,500
-Xss512k ~3,500 ~5,000
-Xss1m ~7,000 ~10,000
-Xss2m ~14,000 ~20,000
实际测试结果可能因 JVM 版本、操作系统和代码结构不同而有所变化。
你可以尝试调整 -Xss 并运行测试代码,看看你的环境下方法调用栈的最大深度是多少! 🚀

线程栈参数的其他含义

线程栈的大小(Xss)可以直观地告诉我们线程的内存开销,假设我们保留 JVM 的默认设置 Xss 为 1M,同时我们在 JVM 中创建了 1000 个线程或者一个包含 1000 个核心线程的线程池,那么 JVM 中光虚拟机栈这部分占用的内存就会达到 1G 左右,而这是很大的一部分内存开销,因此但我们看到 JVM 调优工具中的一个个线程的时候,我们应该想到一个线程内存开销就是 1M