背景:
事情来源于生产的一个异常日志
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的线程没有影响,验证代码如下:
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