讲师中心 微信公众号
AI工具推荐 视频效率加速

在Java里StackOverflowError产生原因_Java递归异常说明

星敏同学_9177

星敏同学_9177

发布时间:2026-01-15 15:12:09

|

350人浏览过

|

来源于php中文网

原创

StackOverflowError是栈空间耗尽而非内存溢出;它由线程栈帧超限引发,与堆内存和GC无关,需通过-Xss调优,根本解决需修复递归终止条件或隐式调用环。

在java里stackoverflowerror产生原因_java递归异常说明

StackOverflowError 是栈空间耗尽,不是内存溢出

Java 中 StackOverflowError 和 OutOfMemoryError 完全不同:前者发生在 JVM 线程栈上,后者才涉及堆内存。每个线程启动时分配固定大小的栈(默认通常 1MB 左右),函数调用、局部变量、方法参数都压入栈帧;一旦调用链太深(尤其是递归没终止),栈帧持续堆积,超出上限就直接抛 StackOverflowError。

  • 它和 GC 无关,调大堆内存(-Xmx)完全无效
  • 真正起作用的是 -Xss 参数,比如 -Xss2m 可把单线程栈设为 2MB
  • 但治标不治本——栈空间再大也扛不住无限递归

最常见诱因:递归缺少边界或边界失效

看似有 if 判断的递归,实际可能永远进不了终止分支。典型例子是参数未正确收敛、整数溢出导致条件恒真、或浮点数精度问题使比较失效。

public static int factorial(int n) {
    if (n == 0) return 1; // 表面看有终止
    return n * factorial(n - 1); // 但若传入负数,n 永远不会等于 0
}
  • 调用 factorial(-1) → factorial(-2) → … 直到栈满
  • 类似地,binarySearch 里 left > right 没写对,或递归调用传了错误的 mid 值,也会跳过终止条件
  • 注意:JVM 不会主动检测“重复调用相同参数”,只管栈深度

容易被忽略的非显式递归场景

不是只有自己写 foo() { foo(); } 才算递归。以下情况同样会层层压栈:

Json Repair Kit
Json Repair Kit

使用 Node.js 评估修复格式错误的 JSON,自动纠正尾随逗号、单引号、未加引号的键等常见问题,实现文件规范化。

下载
  • toString() 方法里意外调用了自身(比如打印对象时触发 toString,而该方法又调用了 System.out.println(this))
  • 重写了 equals() 或 hashCode(),内部又间接引用了当前对象的其他方法,形成隐式调用环
  • 使用 Lombok 的 @Data 时,若字段类型存在循环引用(如 A 持有 B,B 持有 A),生成的 toString() 默认会无限展开
  • Spring AOP 代理 + 递归方法:代理对象调用自身方法可能绕回代理逻辑,造成额外一层调用

如何定位和验证是不是 StackOverflowError

错误堆栈输出非常关键:看最顶端几行是否呈现高度重复的相同方法名,且深度在千级以上(比如连续几百行都是 com.example.Calc.compute(...))。

立即学习“Java免费学习笔记(深入)”;

  • 用 jstack <pid> 抓线程快照,搜索 java.lang.StackOverflowError,观察调用链是否规律性重复
  • 加 JVM 参数 -XX:+PrintGCDetails -XX:+PrintGCTimeStamps 无用——GC 日志里不会出现栈溢出信息
  • IDE 调试时别盲目设断点:如果递归很深,断点可能卡死或根本触发不到终止前的位置;优先改代码加日志,比如在入口打 System.out.println("depth=" + depth)
  • 注意:某些 JVM 版本(如 JDK 8u20+)会对尾递归做有限优化,但 Java 语言本身不支持尾调用消除,不能依赖

递归本身没问题,问题永远出在控制流没走到出口。栈空间是硬限制,没法靠配置兜底;真正要盯紧的是每次递归调用后,状态是否朝着终止条件可靠推进。

热门AI工具

更多
WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

Loomy
Loomy Hot

一款AI工具,主要用于科大讯飞发布的桌面级 AI 助理,比 OpenClaw 更易用、更安全!,适合需要提升相关任务效率的用户。

SkildArt
SkildArt Hot

SkildArt是一款AI文本写作工具,一站式 AI 视觉创作平台。

AionClaw
AionClaw Hot

AionClaw是一款面向办公、创作和编程任务的AI桌面智能体。

蛙蛙写作

一款AI论文写作工具,主要用于超级AI智能写作助手,适合需要提升相关任务效率的用户。

Laper
Laper Hot

Laper是专为编剧、导演和制片人推出的 AI 原生剧本创作工具。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

Atoms
Atoms Hot

Atoms是一款AI智能体工具,第一支自动构建真实业务的 AI 团队。

相关专题

更多
spring框架介绍
spring框架介绍

本专题整合了spring框架相关内容,想了解更多详细内容,请阅读专题下面的文章。

2671

2025.08.06

Java Spring Security 与认证授权
Java Spring Security 与认证授权

本专题系统讲解 Java Spring Security 框架在认证与授权中的应用,涵盖用户身份验证、权限控制、JWT与OAuth2实现、跨站请求伪造(CSRF)防护、会话管理与安全漏洞防范。通过实际项目案例,帮助学习者掌握如何 使用 Spring Security 实现高安全性认证与授权机制,提升 Web 应用的安全性与用户数据保护。

477

2026.01.26

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

6087

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

2588

2023.08.10

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

6087

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

2588

2023.08.10

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

4358

2023.08.10

Gradle插件开发入门教程
Gradle插件开发入门教程

本专题介绍Gradle插件开发的基本流程,涵盖插件类编写、自定义任务注册、扩展参数设计和插件应用方法,帮助你理解插件如何组织构建逻辑,减少多个项目之间的重复配置。

60

2026.10.22

Gradle Wrapper配置教程
Gradle Wrapper配置教程

本专题介绍Gradle Wrapper的基本作用,涵盖文件组成、生成方法、版本配置和任务调用,帮助你理解项目如何使用指定的Gradle版本,减少不同开发环境带来的构建差异。

40

2026.10.22

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
dev.java 官方:Learn Java
dev.java 官方:Learn Java

共0课时 | 0人学习

Java JDBC数据库连接官方教程
Java JDBC数据库连接官方教程

共0课时 | 0人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn