JAVA如何隐藏异常堆栈_关于Java:如何在没有堆栈跟踪的情况下创建/抛出异常?...

本问题已经有最佳答案,请猛点这里访问。

我今天在浏览一些日志时遇到一个奇怪的错误。

它在日志中的显示方式如下:

2014/09/11 15:23:52.801 [CC3A5FDD16035540B87F1B8C5E806588:] WARN a.b.c.Ddd - Main failure

java.lang.NullPointerException: null

2014/09/11 15:23:52.801 [CC3A5FDD16035540B87F1B8C5E806588:] ...

代码如下所示:

} catch (Exception e) {

Ddd.log.warn("Main failure", e);

throw e;

}

如果重要的话,代码位于jsp中。再次在日志中重复相同的异常(正如您期望的throw e)。

我没有任何原因的记录-日志中的上一行显示了查询的执行。在4天的时间内仅发生了两次,似乎并未对系统造成任何损害。

环境:在Java 5的Tomcat下运行的非常繁忙的Web服务。

我并没有要求调试系统的提示-这些错误已久,甚至可能再也不会发生。我只是很困惑如何在没有堆栈跟踪的情况下创建任何异常(尤其是NPE)?

添加

使用的记录器是slf4j驱动的Logback实例。我相信warn方法在这里。不知道该解析为哪种Logback方法,但我相信Throwable参数会被特别对待,并且如果Throwable附加了堆栈跟踪,它将显示在日志中。

LogBack.xml-根据要求:

DEBUG

${log.consolePattern}

${log.dir}/${log.package}.log

${log.pattern}

${log.dir}/${log.package}.%d{yyyy-MM-dd}.%i.log.zip

16MB

90

true

我手动编辑了日志中会话ID之后的值,以删除客户数据。

slf4j 1.6之前; 它专门说不会根据此链接slf4j.org/faq.html#paramException打印堆栈跟踪

@Abhin-谢谢-使用slf4j 1.7.3版-以及所有其他异常,且堆栈跟踪正常。

我已经更新了答案。 如果可行,请接受。

日志输出的格式是什么? 即如何配置logback.xml来呈现日志输出?

@MichaelWiles-好点-也许问题出在记录器本身中!! Logback.xml已发布。

@OldCurmudgeon如果记录器出现问题; 更改为1.7.3不应该有所帮助。

异常本身包含堆栈跟踪信息,即在创建异常时添加的信息。 是否打印堆栈跟踪取决于丢弃异常的异常处理程序。 (当然,重新引发异常的异常处理程序也可以记录堆栈跟踪信息。)

有时,特别是涉及到NullPointers时(以我的经验),jvm可以优化异常的创建和转换,并且堆栈跟踪会丢失(或更准确地说,从不创建)。我怀疑您的问题与某些Java库无关,而与jvm本身有关。

如果您在启动jvm-process时添加了此参数,并且我怀疑是正确的,那么您将获得堆栈跟踪。

-XX:-OmitStackTraceInFastThrow

之前已经有人问过,请在这里查看更多详细信息:

没有StackTrace的Java中的NullPointerException

没有堆栈跟踪的重复异常-如何重置?

注意,这适用于sun / oracle jvm

也许日志不同时记录堆栈跟踪?

这是有关异常没有堆栈跟踪的示例:

try {

throw new Exception() {

@Override

public synchronized Throwable fillInStackTrace() {

return null;

}

};

} catch (Exception e) {

e.printStackTrace();

}

因此,也许该特定异常是一个被#fillInStackTrace()覆盖的自定义异常,但还是很奇怪。

仍然报告它是在我的测试中创建的那行-尽管很好。

"创建的行"是什么意思? 它发生的行不在堆栈跟踪中? 您说堆栈跟踪丢失了。

我的意思是-运行您的示例代码将打印com.oldcurmudgeon.test.Test $ 2,这确实接近我所看到的,但并不完全相同。

看到:

RuntimeException e = new RuntimeException();

e.setStackTrace(new StackTraceElement[0]);

...

e.printStackTrace();

要么:

RuntimeException e = new RuntimeException();

e.setStackTrace(new StackTraceElement[0]);

...

throw e;

您可以使用stacktrace进行操作。

您的第一个示例记录了创建该行的行,第二个示例记录了引发异常的点的完整堆栈跟踪。 很好的提醒setStackTrace可用。

如我所见,可能有以下三个原因:

SLF4J并不总是记录异常(在早期版本中曾经有一些错误)。根据基础的日志记录框架,可能存在其他配置问题。毕竟该异常可能具有堆栈跟踪,只是没有记录。

该异常不是真正的NullPointerException,而是一个不同的异常,其中覆盖了toString()和fillInStackTrace()方法(前者打印NPE,后者跳过填充堆栈跟踪)。

NPE是通过序列化(而不是通常的构造函数)创建的,并且一直丢失堆栈跟踪。

根据此链接,堆栈跟踪不会在1.6之前的slf4j中打印。版本大于1.6可以解决此问题。

如果它是log.warn("Main failure {}", e);就是这种情况。 在这种情况下,记录器知道它是第二个参数中的Exception,因此将堆栈跟踪记录在其中。

好。 如果您的警告方法将其视为Exception; 那么您可能必须看看Exception的创建或操作方式。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值