最简单方法就是 无限递归:
public class StackOverflowDemo {
public static void recursiveMethod(int count) {
System.out.println(count);
recursiveMethod(count + 1); // 无终止条件
}
public static void main(String[] args) {
try {
recursiveMethod(1);
} catch (StackOverflowError e) {
System.err.println("Stack overflow detected!");
e.printStackTrace();
}
}
}
运行结果:
1
2
3
...
Stack overflow detected!
java.lang.StackOverflowError
at StackOverflowDemo.recursiveMethod(StackOverflowDemo.java:6)
at StackOverflowDemo.recursiveMethod(StackOverflowDemo.java:6)
at StackOverflowDemo.recursiveMethod(StackOverflowDemo.java:6)
...
栈溢出位置在 recursiveMethod
堆栈信息中会重复显示递归调用链 → 热点方法
控制栈大小
通过 JVM 参数 -Xss 调整:
java -Xss256k StackOverflowDemo
栈小 → 更快触发溢出
栈大 → 可以支持更深递归
可以用来测试不同递归深度下栈使用情况
定位栈溢出
Java 堆栈信息已经非常直观:
at StackOverflowDemo.recursiveMethod(StackOverflowDemo.java:6)
步骤:
找到 最后一次调用的方法 → 这是热点溢出点
检查递归/方法调用链
确认终止条件是否缺失
使用 IDE 调试器(断点 + 调试模式)可以看到递归深度和变量变化
例:多层调用栈
public class MultiMethodStack {
public static void methodA() {
methodB();
}
public static void methodB() {
methodC();
}
public static void methodC() {
methodA(); // 无限循环调用
}
public static void main(String[] args) {
try {
methodA();
} catch (StackOverflowError e) {
e.printStackTrace();
}
}
}
输出示例:
java.lang.StackOverflowError
at MultiMethodStack.methodC(MultiMethodStack.java:10)
at MultiMethodStack.methodA(MultiMethodStack.java:6)
at MultiMethodStack.methodB(MultiMethodStack.java:7)
at MultiMethodStack.methodC(MultiMethodStack.java:10)
...
可以看到调用链:A → B → C → A → B → C ...
堆栈信息能帮你 精准定位循环调用 或递归
分析栈溢出原因
常见原因:
递归未结束
忘记终止条件
终止条件逻辑错误
深度方法调用
循环调用方法过深
多线程每个线程栈太小也可能溢出
JVM 栈空间不足
栈本身太小,正常递归也可能溢出
调优建议
对递归算法:
优化为 尾递归(JVM 部分可优化)
使用 循环代替递归
调整 JVM 栈大小:-Xss1m
对深度调用的多线程应用,增加线程栈大小
高级定位方法
生成线程 dump(jstack <pid>)
可以看到每个线程的完整调用栈
对定位复杂调用链有用
结合 -XX:+PrintCompilation / JMH
如果栈溢出出现在性能热点方法,可以结合 JIT 编译分析优化方法
IDE 调试器
设置断点,跟踪递归深度和变量状态
IntelliJ IDEA、Eclipse 都支持观察栈帧
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70050070/viewspace-3117518/ ,如需转载,请注明出处,否则将追究法律责任。