我最近发现,导致一个NullPointerException异常的错误。 该例外被捕获,并使用标准的SLF4J声明记录。 下面简略的代码:
for(Action action : actions.getActions()) {
try {
context = action.execute(context);
} catch (Exception e) {
logger.error("...", e);
break;
}
}
正如你所看到的,没有什么花哨。 然而,所有我们有异常记录报表,仅这一项不打印堆栈跟踪。 所有它打印为消息(表示为“...”)以及异常类(显示java.lang.NullPointerException)的名称。
由于在异常堆栈跟踪是延迟加载,我想也许有一个指令重新排序某种问题,并决定日志语句之前调用e.getStackTrace()。 这并没有区别。
所以我决定重新启用调试代理。 但是,因为我甚至附着的过程中,我注意到,现在的堆栈跟踪进行打印。 所以很明显调试代理的存在造成了一些额外的调试信息变得可用。
我从那时起固定异常的根本原因。 不过,我想了解为什么堆栈跟踪是没有一个调试器不可用。 任何人都知道吗?
澄清: 这不是一个记录的问题 。 想象一下,同一个try / catch子句,但在抓,我打印的价值:
e.getStackTrace().length
如果没有这个调试器打印“0”,与调试器它打印(在这种情况下9)的正数。
更多信息:这是发生在JDK 1.6.0_13,64位,AMD64的Linux 2.6.9
难道这个代码是在内部循环? 然后再JIT编译器可能会被编译调用堆栈这为本地代码,失去了堆栈信息。 然后,当你连接调试程序,它禁用了JIT,从而再次可用的信息。
其他手动例外持续显示信息作为JIT不优化。
它看起来像这样有时会从在管线102这个类的源代码中的注释发生他人:
http://logging.apache.org/log4j/1.2/xref/org/apache/log4j/spi/LocationInfo.html
随着JVM标志-XX:-OmitStackTraceInFastThrow您可以禁用JVM的性能优化这个用例。 如果这个参数是给定的,禁用的标志,堆栈跟踪将可用。
欲了解更多信息,请看看下面的发行说明:
“在服务器虚拟机现在提供正确的堆栈回溯编译器的所有的‘冷’内置例外。为了改进性能,当这样的异常被抛出了几下,该方法可以被重新编译。重新编译后,编译器可以选择。更快的战术使用预分配的例外,不提供堆栈跟踪要完全禁止使用预分配异常,使用这个新的标志:-XX:-OmitStackTraceInFastThrow” http://java.sun.com/j2se/1.5.0/relnotes.html
我可以复制这一点,但它似乎有点奇怪,这将在您的行动某处发生。
如果调用setStackTrace与空数组,这会导致显示只有文字。
public class Fark {
public static void main(String[] args) {
try {
Fark.throwMe(args.length != 0);
}
catch (Exception e) {
e.printStackTrace();
}
}
public static final void throwMe(boolean arg) throws Exception{
Exception e = new NullPointerException();
if (arg) {
e.setStackTrace(new StackTraceElement[0]);
}
throw e;
}
}
运行它....
% java Fark
java.lang.NullPointerException
at Fark.throwMe(Fark.java:15)
at Fark.main(Fark.java:5)
% java Fark nothing
java.lang.NullPointerException