First example:
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);
}
}
}
Output:
Error:
java.lang.RuntimeException: java.lang.NullPointerException: NPE
at Main.main(Main.java:10)
In the second example we just add a message to the RuntimeException
also:
throw new RuntimeException("RTE", new NullPointerException("NPE"));
Output:
Error:
java.lang.RuntimeException: RTE
at Main.main(Main.java:10)
Why is NullPointerException
not logged in this case?
Note: e.printStackTrace()
prints both exceptions in both cases:
java.lang.RuntimeException: RTE
at Main.main(Main.java:10)
Caused by: java.lang.NullPointerException: NPE
... 1 more
Versions:
slf4j-api: 1.7.12
slf4j-log4j12: 1.7.12
log4j: 1.2.17
There are 2 issues.
Ans:
Actually
SLF4J has no impact on that case
. It is pure JVM issue. In JVM, it is required to compute every passed parameter before function call. If you follow this 2 examples, you can easily understood that issue.Example 1:
Output:
Here,
"java.lang.NullPointerException: NPE"
- this portion is used as message according to RuntimeException which one is also generated from another exception NullPointerException(String s)Example 2:
Output:
Here
"RTE"
is used as message.In your code, you have used 3 times exceptions. That's not good coding.
e.printStackTrace()
prints this throwable and its backtrace to the standard error stream. It prints a stack trace for this Throwable object on the error output stream that is the value of the fieldSystem.err
As your output is:["java.lang.RuntimeException: RTE"]
contains the result of the toString() method for this Throwable object.The backtrace for a throwable with an initialized, non-null cause should generally include the backtrace for the cause. The format of this information depends on the implementation. For your clear understanding, go through the backtrace example below:
"... 1"
These lines indicate that the remainder of the stack trace for this exception matches the indicated number of frames from the bottom of the stack trace of the exception that was caused by this exception (the "enclosing" exception).
Resource Link:
For
SLF4J
, you can go throughSystem.out
andSystem.err
to an SLF4J defined logger with the name of the fully qualified class in which theSystem.out.println
(or similar) call was made, at configurable levels.runtime
rather thancompile-time
.I had similar problem when I was using Slf4j Logger in my Apache Spark application running on cluster mode. As I found out problem in my case was caused by JVM optimization related to
OmitStackTraceInFastThrow
which was basically not printing whole stack just top level error without any details.In your case this might be hiding error message from
NullPointerException
. Try adding this argument to JVM-XX:-OmitStackTraceInFastThrow
when starting your application and let us know if it works.Giving it a possible try using all the docs and debugging I could, I hope this helps in whatever way it can :
So both your cases are including the stack-trace of the RuntimeException thrown by the statement of code. Not much of a difference.
Case 1 :
throw new RuntimeException(new NullPointerException("NPE"));
Quoting from the RuntimeException Java-Doc and NullPointerException Java-Doc
So that possibly answers the first part of your question where
java.lang.RuntimeException
is thrown during execution which is caused by thenew NullPointerException
but ascause==null
evaluates to false thecause.toString()
is printed i.ejava.lang.NullPointerException
and now since this exception itself has a message passed that follows asNPE
Note : You have mentioned the cause as NullPointerException in your code.(hence
cause==null
evaluates to false)Case 2 :
throw new RuntimeException("RTE", new NullPointerException("NPE"))
In which case you end up getting
java.lang.RuntimeException
being thrown with a messageRTE
since your cause is a child ofRuntimeException
itself and the parent is caught first, it gets executed and the child is not reached in this case.I noticed that in the
log4j.properties
file I'm using there is the following line:It seems to be causing the
caused by
elements to be omitted when the exception is logged.Once removed, the full stack trace is logged.