29_线程栈内存溢出
545字约2分钟
2024-08-10
线程的栈内存如何溢出的
如下所示代码,JVM
启动之后,加载类到内存中,通过 main
线程执行 main()
方法
此时在 main
线程的虚拟机栈里,就会压入 main()
方法对应的栈帧,里面也会放入 main
方法中 word
这个局部变量
每个线程的虚拟机栈内存大小可以手动设置的,一般默认是设置 1MB
main
方法中调用了 sayHello()
方法,此时会继续将 sayHello()
方法的栈帧压入到 main
线程的虚拟机栈中去
public static void main(String[] args) {
String word = "hello";
sayHello(word);
}
public static void sayHello(String content) {
System.out.println(content);
}
虽然一些变量和数据占用不了太大内存,但是每次方法调用的栈帧也是会占用内存的
一个线程的虚拟机栈内存大小是有限的,比如 1MB
,如果不停的在这个线程去调用各种方法,然后不停的把方法调用栈帧压入栈中
一直不停的放入栈帧,一旦大量的栈帧消耗完这 1MB
的线程栈内存,最终会出现栈内存溢出的情况
模拟线程的栈内存溢出
JVM
参数中设置线程栈内存大小 -Xss1M
,这里设置为 1MB
在代码中我们递归调用 sayHello
方法,直到线程栈内存溢出
我们可以看到栈内存溢出日志内容 StackOverflowError
,也很清晰的看到是由于 StackMemoryDemo
中 sayHello
这个方法锁导致的
/**
* @ClassName StackMemoryDemo
* @Desciption 栈内存溢出 Demo
* @Author MaRui
* @Date 2024/2/6 14:33
* @Version 1.0
*/
public class StackMemoryDemo {
public static long count = 0;
public static void main(String[] args) {
sayHello();
}
public static void sayHello() {
System.out.println("这是第 " + (++count) + " 次 say hello" );
sayHello();
}
}
这是第 6425 次 say hello
Exception in thread "main" java.lang.StackOverflowError
at com.marui.utils.jvm.StackMemoryDemo.sayHello(StackMemoryDemo.java:19)
at com.marui.utils.jvm.StackMemoryDemo.sayHello(StackMemoryDemo.java:20)
at com.marui.utils.jvm.StackMemoryDemo.sayHello(StackMemoryDemo.java:20)
at com.marui.utils.jvm.StackMemoryDemo.sayHello(StackMemoryDemo.java:20)
at com.marui.utils.jvm.StackMemoryDemo.sayHello(StackMemoryDemo.java:20)
at com.marui.utils.jvm.StackMemoryDemo.sayHello(StackMemoryDemo.java:20)
线程的栈内存溢出解决
通过分析日志就很明确知道 StackMemoryDemo
类中 sayHello
方法被频繁调用导致的栈内存溢出