JVM之消失的堆栈:-XX:-OmitStackTraceInFastThrow

问题描述

近期查看测试环境日志,经常会打印一些没有堆栈的异常信息,对问题排查无疑是致命的。

java.lang.NullPointerException
java.lang.NullPointerException
java.lang.NullPointerException
java.lang.NullPointerException

第一反应是"什么鬼?",难得是日志组件出BUG了。后面才得知jvm针对频繁出现的异常做了优化,可以在出现异常的时候快速抛出,不需要打印出整个调用链,这样可以节省异常堆栈的内存分配。既然jvm针对这个做了优化,那肯定有禁用这个优化的方法,那就是-XX:-OmitStackTraceInFastThrow参数(禁用快抛,即展示完整异常),如果使用-XX:+OmitStackTraceInFastThrow则代表启用快抛,即会存在一些没有完整堆栈的异常。

测试

不加jvm参数,默认是启用快抛
public class WithNPE extends Thread {
    private static int count = 0;

    @Override
    public void run() {
        try{
            System.out.println(this.getClass().getSimpleName()+"--"+(++count));
            String str = null;
            // 制造空指针NPE
            System.out.println(str.length());
        }catch (Throwable e){
            e.printStackTrace();
        }
    }
}

public class FastThrowMain {
    public static void main(String[] args) throws InterruptedException {
        WithNPE withNPE = new WithNPE();
        ExecutorService executorService = Executors.newFixedThreadPool(20);
        for (int i=0; i

增加-XX:-OmitStackTraceInFastThrow参数:

禁用快抛,全是完整异常:
java.lang.NullPointerException
    at com.xx.xx.mpp.WithNPE.run(WithNPE.java:18)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
java.lang.NullPointerException
    at com.xx.xx.mpp.WithNPE.run(WithNPE.java:18)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)

总结

主要是了解jvm针对异常机制有这个优化,然后针对某些错误场景很难排查问题时可以禁用这个优化。如果日志保存的时间比较长,可以往上找,因为jvm的异常机制只是针对频率比较高的情况做了优化,肯定会存在一些完整堆栈的异常的。

你可能感兴趣的:(JVM之消失的堆栈:-XX:-OmitStackTraceInFastThrow)