菜单 学习猿地 - LMONKEY

VIP

开通学习猿地VIP

尊享10项VIP特权 持续新增

知识通关挑战

打卡带练!告别无效练习

接私单赚外块

VIP优先接,累计金额超百万

学习猿地私房课免费学

大厂实战课仅对VIP开放

你的一对一导师

每月可免费咨询大牛30次

领取更多软件工程师实用特权

入驻
0
0

Java异常日志堆栈丢失原因

原创
05/13 14:22
阅读数 204

推荐课程:Java开发工程师--学习猿地--送7个上线商业项目

查日志是我们排查问题的重要手段之一,直接又方便。其中异常日志堆栈信息可以让我们快速的发现问题所在,但稍微有点经验的开发应该会遇到过日志堆栈信息丢失的情况。
堆栈只打印了一行:java.lang.NullPointerException,然后什么信息都没有了,这是怎么回事?
如果面试中,就可以提一些问题:
什么情况下Java的异常日志堆栈信息会丢失?其原因是什么? 异常堆栈丢失情况下要如何排查问题?
原因
JVM内部同一个方法被调用多次的时候,会被JIT编译器进行优化,在Oracle官方文档中,有一段英文描述:

The compiler in the server VM now provides correct stack backtraces for all "cold" built-in exceptions. For performance purposes, when such an exception is thrown a few times, the method may be recompiled. After recompilation, the compiler may choose a faster tactic using preallocated exceptions that do not provide a stack trace. To disable completely the use of preallocated exceptions, use this new flag: -XX:-OmitStackTraceInFastThrow.

在Server模式下的JVM编译器提供了一种方式可以让我们回溯异常的堆栈信息,但是出于性能的因素,当类似的异常抛出多次的时候,异常方法可以被重新编译,重新编译后,编译器会采用更快的策略使用预分配缓存区的异常,并且不再提供堆栈信息。
如果不想使用预分配缓存的异常使用-XX:-OmitStackTraceInFastThrow标记。
另外一方面异常栈的获取是非常消耗性能的,这点通过JVM内部默认会对一些异常不进行堆栈回溯也可以看出。
异常丢失如何排查

试着隔离一两台机器,重启两台机器观察情况
-XX:-OmitStackTraceInFastThrow可以控制不进行异常堆栈优化,如果关闭,就需要预防产生“日志风暴”,否则,一旦高频应用出现异常可能很快用满服务器磁盘。

验证堆栈丢失Demo
public class ExceptionLossDemo {
public static void main(String[] args) {
boolean flag = false;
for (int i = 0;;i++){
boolean isExceptionStackLoss = exceptionTest();
if (isExceptionStackLoss) {
flag = true;
System.out.println("times:" + i + ", res:" + isExceptionStackLoss);
} else if (flag) {
System.out.println("times:" + i + ", res:" + isExceptionStackLoss);
}
}
}

public static boolean exceptionTest() {
    try {
        // 构造一个NPE异常
        int res = ((Integer)null) + 1;
    } catch (Exception e) {
        if (e.getStackTrace().length == 0) {
            // 打印堆栈信息
            e.printStackTrace();
            try {
                // 当出现 NPE 异常堆栈为空的时候,停留5秒,便于观察
                Thread.sleep(5000);
            } catch (Exception e1) {
            }
            // 如果出现 NPE 异常堆栈为空,返回true
            return true;
        }
        // 打印堆栈信息
        e.printStackTrace();
    }

    return false;
}

}
复制代码
file
最后
希望对大家有所帮助,技术不断精进..

作者:Real_man
链接:https://juejin.im/post/6893310477397393421
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

发表评论

0/200
0 点赞
0 评论
收藏
为你推荐 换一批