异常堆栈丢失的解决方法 - 极悦
专注Java教育14年 全国咨询/投诉热线:444-1124-454
极悦LOGO图
始于2009,口口相传的Java黄埔军校
首页 hot资讯 异常堆栈丢失的解决方法

异常堆栈丢失的解决方法

更新时间:2021-08-23 11:52:51 来源:极悦 浏览1634次

登陆服务器进行例行的检查,发现异常日志文件里有很多nullPointException,只有简单的异常名称,却没有堆栈信息。没有异常堆栈,无法定位错误,也就不能修改了。

正确的解决方法是增加一个VM Options:-XX:-OmitStackTraceInFastThrow。这个参数的好处如下:

“JVM对一些特定的异常类型做了Fast Throw优化,如果检测到在代码里某个位置连续多次抛出同一类型异常的话,C2会决定用Fast Throw方式来抛出异常,而异常Trace即详细的异常栈信息会被清空。这种异常抛出速度非常快,因为不需要在堆里分配内存,也不需要构造完整的异常栈信息。”

这个参数,支持的异常类型如下:

NullPointerException

ArithmeticException

ArrayIndexOutOfBoundsException

ArrayStoreException

ClassCastException

通过这个方案,开启输出空指针错误,很快就定位问题,并解决了。

解决问题后,进行了一番的测试和验证,如下:

问题验证

在异常出现5000次以上时,才会丢失堆栈信息。在6600多次的时候丢失堆栈信息,但是并不稳定。代码如下:

public class JavaNPE extends Thread {
    private static int count = 0;
    @Override
    public void run() {
        try {
            System.out.println("getSimpleName is:"+this.getClass().getSimpleName() + " execute count:" + (++count));
            String str = null;
            System.out.println(str.length());        } catch (Throwable e) {
            e.printStackTrace();        }    }}public class TestFastThrow {
    public static void main(String[] args) throws InterruptedException {
        JavaNPE javaNPE = new JavaNPE();
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        for (int i = 0; i < Integer.MAX_VALUE; i++) {
            executorService.execute(javaNPE);            //防止打出的日志太快
            Thread.sleep(2);
        }
    }
}

这是一个多线程的程序,写单线程的测试程序,是否可行呢?于是就尝试了第一版,代码如下:

public static void main(String args[]) {
        for (int i = 0; i < 10000; i++) {
            try {
                String value = null;
                value.substring(0, 100);
            } catch (Exception ex) {
                ex.printStackTrace();            }        }    }

但是,很遗憾,这个程序的异常堆栈信息并不会丢失。程序修改如下:

public void method2() {
        String value = null;
        value.substring(0, 100);
    }    public static void main(String args[]) {
        ExceptionTest exceptionTest = new ExceptionTest(1);
        for (int i = 0; i < 10000; i++) {
            try {
                exceptionTest.method2();            } catch (Exception ex) {
                ex.printStackTrace();            }        }    }

这个程序在第5530~5550次的时候,会丢失异常堆栈信息,是不稳定的。分析上述两段单线程的测试代码,第一段因为异常信息没有到方法的外面,jvm不能追踪到异常堆栈信息,所以并不会起作用。

以上就是极悦小编介绍的"异常堆栈丢失的解决方法",希望对大家有帮助,想了解更多可查看Java堆栈。极悦在线学习教程,针对没有任何Java基础的读者学习,让你从入门到精通,主要介绍了一些Java基础的核心知识,让同学们更好更方便的学习和了解Java编程,感兴趣的同学可以关注一下。

提交申请后,顾问老师会电话与您沟通安排学习

免费课程推荐 >>
技术文档推荐 >>