StackOverflowError的JVM处理方式

背景:

事情来源于生产的一个异常日志
Caused by: java.lang.StackOverflowError: null at java.util.stream.Collectors.lambda$groupingBy$45(Collectors.java:908) at java.util.stream.ReduceOps$3ReducingSink.accept(ReduceOps.java:169) at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1382)

发生该异常并定位到是某个规则的问题后,我们手动修复了规则,不过我们无法确定是否需要重启容器,所以引申出来了发生StackOverflowError是否需要重启容器恢复的讨论

JVM对StackOverflowError线程的处理

结论是JVM只会中断发生StackOverflowError的线程,对于其他未发生StackOverflowError的线程没有影响,验证代码如下:

java 复制代码
package stackoverflow;

/**
 * 验证JVM处理StackOverflowError的方式,只会中断异常线程,不影响主线程以及其他线程的执行
 */
public class StackOverFlowTest {


    public static void main(String[] args) throws Exception {
        Thread stackOverflowErrorThread = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(60000L);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                // 进入死循环
                callRecursiveMethod();
            }
        }, "StackOverflowErrorThread");

        Thread otherNormalThread = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    System.out.println("I am otherNormalThread thread!!");
                    try {
                        Thread.sleep(10000L);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }, "otherNormalThread");

        stackOverflowErrorThread.start();
        otherNormalThread.start();

        Thread.currentThread().setName("mainThread");
        while (true) {
            System.out.println("I am main thread!!");
            try {
                Thread.sleep(10000L);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }

    /**
     * 死循环模拟StackOverflowError
     */
    public static void callRecursiveMethod() {
        callRecursiveMethod();
    }



}

未发生Stack Overflow之前

发生Stack Overflow之后

从输入日志也可以验证这一点:

参考:

https://blog.csdn.net/u011983531/article/details/79563162

相关推荐
秋夫人11 小时前
jvm G1 垃圾收集日志分析示例(GC)
jvm
天天向上杰11 小时前
简识JVM的栈帧优化共享技术
java·jvm
讓丄帝愛伱14 小时前
不重启JVM,替换掉已经加载的类
jvm
qq_3127384514 小时前
jvm学习总结
jvm·学习
天天向上杰14 小时前
简识JVM栈中的程序计数器
jvm
大乔乔布斯14 小时前
JRE、JVM 和 JDK 的区别
java·开发语言·jvm
天天向上杰15 小时前
简识JVM栈帧中的局部变量表
jvm
小白的一叶扁舟1 天前
深入剖析 JVM 内存模型
java·jvm·spring boot·架构
小池先生1 天前
jvm_threads_live_threads 和 jvm_threads_states_threads 这两个指标之间存在一定的关系,但它们关注的维度不同
jvm
{⌐■_■}2 天前
【GORM】事务,嵌套事务,保存点事务的使用,简单电商平台go案例
开发语言·jvm·后端·mysql·golang