第一个例子:
public class Main {
private static final Logger logger = LoggerFactory.getLogger(Main.class);
public static void main(String[] args) throws Exception {
try {
throw new RuntimeException(new NullPointerException("NPE"));
} catch (RuntimeException e) {
logger.error("Error:", e);
}
}
}
输出:
Error:
java.lang.RuntimeException: java.lang.NullPointerException: NPE
at Main.main(Main.java:10)
在第二个示例中,我们只是向RuntimeException
添加消息:
throw new RuntimeException("RTE", new NullPointerException("NPE"));
输出:
Error:
java.lang.RuntimeException: RTE
at Main.main(Main.java:10)
为什么在这种情况下没有记录NullPointerException
?
注意:e.printStackTrace()
在两种情况下都会打印两个例外:
java.lang.RuntimeException: RTE
at Main.main(Main.java:10)
Caused by: java.lang.NullPointerException: NPE
... 1 more
版本:
slf4j-api: 1.7.12
slf4j-log4j12: 1.7.12
log4j: 1.2.17
答案 0 :(得分:6)
尽可能尝试使用所有文档并进行调试,我希望这有助于它以任何方式:
@param message the message object to log.
@param t the exception to log, including its stack trace.
public void error(Object message, Throwable t)
因此,两种情况都包括代码语句抛出的RuntimeException的堆栈跟踪。没什么区别。
案例1 : throw new RuntimeException(new NullPointerException("NPE"));
引用RuntimeException Java-Doc和NullPointerException Java-Doc
public RuntimeException(Throwable cause)
使用指定的cause和a构造一个新的运行时异常
(cause==null ? null : cause.toString())
的详细信息(其中 通常包含原因的类和详细信息。这个 构造函数对于稍微多于的运行时异常非常有用 其他扔掉的包装纸。
public NullPointerException(String s)
使用指定的详细消息构造NullPointerException。
因此,可能会回答问题的第一部分,其中 java.lang.RuntimeException
在执行期间被new NullPointerException
引起但是{ {1}}评估为 false 打印cause==null
,即 cause.toString()
,现在由于此异常本身传递的消息为 java.lang.NullPointerException
注意:您在代码中已将原因称为NullPointerException。(因此NPE
计算结果为false)
案例2 : cause==null
throw new RuntimeException("RTE", new NullPointerException("NPE"))
使用指定的详细消息构造新的运行时异常 和原因。请注意,与原因关联的详细消息不是 自动合并到此运行时异常的详细消息中。
在这种情况下,由于您的原因是{{1}的孩子,您最终会收到 public RuntimeException(String message, Throwable cause)
并收到消息 java.lang.RuntimeException
本身和父亲首先被捕获,它被执行,在这种情况下没有到达子女。
答案 1 :(得分:1)
有2个问题。
- 为什么在这种情况下不记录NullPointerException [throw new RuntimeException(" RTE",new NullPointerException(" NPE"));]?
醇>
实际上SLF4J has no impact on that case
。这是纯粹的JVM问题。在JVM中,需要在函数调用之前计算每个传递的参数。如果您按照这两个示例进行操作,则可以轻松理解该问题。
示例1:
public class Main {
public static void main(String[] args) {
throw new RuntimeException(new NullPointerException("NPE"));
}
}
输出:
Exception in thread "main" java.lang.RuntimeException: java.lang.NullPointerException: NPE // Here, "java.lang.NullPointerException: NPE" - this portion is used as message according to RuntimeException
at Main.main(Main.java:3)
Caused by: java.lang.NullPointerException: NPE
... 1 more
这里,"java.lang.NullPointerException: NPE"
- 根据RuntimeException将此部分用作消息,其中一部分也是从另一个异常NullPointerException(String s)生成的
示例2:
public class Main {
public static void main(String[] args) {
throw new RuntimeException("RTE", new NullPointerException("NPE"));
}
}
输出:
Exception in thread "main" java.lang.RuntimeException: RTE // Here "RTE" is used as message
at Main.main(Main.java:3)
Caused by: java.lang.NullPointerException: NPE
... 1 more
此处"RTE"
用作消息。
在您的代码中,您使用了3次异常。这不是很好的编码。
- 为什么e.printStackTrace()会在两种情况下都打印两个例外?
醇>
e.printStackTrace()
将此throwable及其回溯打印到标准错误流。它在错误输出流上打印此Throwable对象的堆栈跟踪,该跟踪是字段System.err
的值
您的输出是:
java.lang.RuntimeException: RTE
at Main.main(Main.java:10)
Caused by: java.lang.NullPointerException: NPE
... 1 more
["java.lang.RuntimeException: RTE"]
的第一行
包含此Throwable的toString()方法的结果
对象。具有初始化非null原因的可抛出的回溯 通常应包括原因的回溯。格式 这些信息取决于实施情况。为了你的清楚 理解,请看下面的回溯示例:
HighLevelException: MidLevelException: LowLevelException
at Junk.a(Junk.java:13)
at Junk.main(Junk.java:4)
Caused by: MidLevelException: LowLevelException
at Junk.c(Junk.java:23)
at Junk.b(Junk.java:17)
at Junk.a(Junk.java:11)
... 1 more
Caused by: LowLevelException
at Junk.e(Junk.java:30)
at Junk.d(Junk.java:27)
at Junk.c(Junk.java:21)
... 3 more
" ... 1"
这些行表示堆栈的其余部分为此跟踪 异常匹配来自底部的指定帧数 由此异常引起的异常的堆栈跟踪 ("附上"例外)。
对于SLF4J
,您可以通过
System.out
和
System.err
到SLF4J定义的记录器,名称为完全
System.out.println
(或类似)调用的限定类
是在可配置的级别制作的。runtime
而不是compile-time
。答案 2 :(得分:0)
当我在群集模式下运行的Apache Spark应用程序中使用Slf4j Logger时,我遇到了类似的问题。我发现问题在我的情况下是由与OmitStackTraceInFastThrow
相关的JVM优化引起的,基本上没有打印整个堆栈只是顶级错误而没有任何细节。
在您的情况下,这可能会隐藏NullPointerException
的错误消息。尝试在启动应用程序时将此参数添加到JVM -XX:-OmitStackTraceInFastThrow
,并告诉我们它是否有效。