Object string = "abcd";
int i = 0;
while (i < 12289) {
i++;
try {
Integer a = (Integer) string;
} catch (Exception e) {
e.printStackTrace();
}
}
对于这个特定的代码片段,12288次迭代(频率?)似乎是JVM决定使用预分配异常的限制...
1
当您在项目中使用AspectJ时,可能会发生某些方面隐藏其堆栈跟踪的部分 . 例如,今天我有:
java.lang.NullPointerException:
at com.company.product.MyTest.test(MyTest.java:37)
通过Maven的万无一失运行测试时打印出这个堆栈跟踪 .
另一方面,在IntelliJ中运行测试时,会打印出不同的堆栈跟踪:
java.lang.NullPointerException
at com.company.product.library.ArgumentChecker.nonNull(ArgumentChecker.java:67)
at ...
at com.company.product.aspects.CheckArgumentsAspect.wrap(CheckArgumentsAspect.java:82)
at ...
at com.company.product.MyTest.test(MyTest.java:37)
10 回答
正如您在评论中提到的,您正在使用log4j . 我(无意中)发现了我写过的地方
而不是典型的
通过懒惰或者可能只是不考虑它 . 不幸的是,它不像你期望的那样表现 . Logger API实际上将Object作为第一个参数,而不是字符串 - 然后它在参数上调用toString() . 因此,它不是获得漂亮的漂亮堆栈跟踪,而是打印出toString - 在NPE的情况下它是非常无用的 .
也许这就是你所经历的?
替代建议 - 如果您正在使用Eclipse,则可以在NullPointerException本身上设置断点(在Debug透视图中,转到“Breakpoints”选项卡并单击其中包含!的小图标)
检查“捕获”和“未捕获”选项 - 现在当您触发NPE时,您将立即断点,然后您可以逐步查看它是如何处理的以及为什么您没有获得堆栈跟踪 .
exception.toString没有给你StackTrace,它只返回
请改用exception.printStackTrace来输出StackTrace .
toString()
仅返回异常名称和可选消息 . 我建议打电话转储消息,或者如果您需要血淋淋的细节:
我们过去曾见过同样的行为 . 事实证明,出于某些疯狂的原因,如果NullPointerException多次发生在代码中的同一位置,使用
Log.error(String, Throwable)
一段时间后将停止包括完整的堆栈跟踪 .尝试进一步查看日志 . 你可能会找到罪魁祸首 .
EDIT: this bug听起来很相关,但很久以前就修好了它可能不是原因 .
(您的问题仍然不清楚您的代码是否正在调用
printStackTrace()
或者这是由日志记录处理程序完成的 . )以下是可能发生的事情的一些可能的解释:
正在使用的 Logger /处理程序已配置为仅输出异常的消息字符串,而不是完整的堆栈跟踪 .
您的应用程序(或某些第三方库)使用
LOG.error(ex);
而不是(例如)log4j Logger方法的2参数形式记录异常 .消息来自与您认为的不同的地方;例如它实际上是一些第三方库方法,或者是早期尝试调试时留下的一些随机内容 .
正在记录的异常重载了一些隐藏堆栈跟踪的方法 . 如果是这种情况,异常将不是真正的NullPointerException,而是NPE的一些自定义子类型甚至是一些未连接的异常 .
我认为最后可能的解释是不太可能的,但人们至少会考虑做这种事情来“防止”逆向工程 . 当然,只有真正成功地让诚实的开发人员生活困难 .
这是一个解释:Hotspot caused exceptions to lose their stack traces in production – and the fix
我在Mac OS X上测试过它
java版"1.6.0_26"
Java(TM)SE运行时环境(版本1.6.0_26-b03-383-11A511)
Java HotSpot(TM)64位服务器VM(内置20.1-b02-383,混合模式)
对于这个特定的代码片段,12288次迭代(频率?)似乎是JVM决定使用预分配异常的限制...
当您在项目中使用AspectJ时,可能会发生某些方面隐藏其堆栈跟踪的部分 . 例如,今天我有:
通过Maven的万无一失运行测试时打印出这个堆栈跟踪 .
另一方面,在IntelliJ中运行测试时,会打印出不同的堆栈跟踪:
您可能正在使用Sun JVM,它执行大量优化 . 要恢复堆栈跟踪,需要将选项
-XX:-OmitStackTraceInFastThrow
传递给JVM .现代的OpenJDK JVM(1.8及更高版本?)似乎也接受了
-XX:-OmitStackTraceInFastThrow
标志(默认情况下也启用了堆栈跟踪优化) .这将输出Exception,仅用于调试,您应该更好地处理异常 .