java日志不打印异常栈

问题描述

今天在排查一个问题的时候发现在日志输出中,只有异常的Message,并没有详细的异常堆栈。

问题解释

对于这个问题的官方解释为:

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.

简单的描述就是:

它跟JDK5的一个新特性有关,对于一些频繁抛出的异常,JDK为了性能会做一个优化,即JIT重新编译后会抛出没有堆栈的异常, 而在使用-server模式时,该优化选项是开启的,因此在频繁抛出某个异常一段时间后,该优化开始起作用,即只抛出没有堆栈的异常信息

问题验证

比如下面的程序:

public class TestCompile {
	private static final int count = 1000000;

	public static void main(String[] args) throws Exception {
		int index = count;
		while (index-- > 0) {
			try {
				work();
			}
			catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	private static void work() {
		String value = null;
		value.length();
	}
}

编译后使用java -server -XX:-OmitStackTraceInFastThrow TestCompile运行,发现一直都是类似的stacktrace。

java.lang.NullPointerException
at TestCompile.work(TestCompile.java:25)
at TestCompile.main(TestCompile.java:17)

换成java -server -XX:+OmitStackTraceInFastThrow TestCompile运行一段时间后就会出现

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

这样的exception,说明stacktrace 该优化已经起作用。-XX:+OmitStackTraceInFastThrow选项在-server情况下默认开启。

如何解决

  • 方法1:查看很早之前的日志,那个时候jit的优化还没生效
  • 方法2:重启服务,在重启的以后的一段时间内jit的优化也暂时不会生效
  • 方法3:配置参数-XX:-OmitStackTraceInFastThrow
comments powered by Disqus