可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I\'ve had instances of our Java code catch a NullPointerException
, but when I try to log the StackTrace (which basically ends up calling Throwable.printStackTrace()
), all I get is:
java.lang.NullPointerException
Has anyone else come across this? I tried googling for \"java null pointer empty stack trace\" but didn\'t come across anything like this.
回答1:
You are probably using the Sun JVM, which performs a lot of optimization. To get the stack traces back, you need to pass the option -XX:-OmitStackTraceInFastThrow
to the JVM.
Modern OpenJDK JVMs (1.8 and higher?) seem to accept the -XX:-OmitStackTraceInFastThrow
flag as well (and have stack-trace optimization turned on by default) as well.
回答2:
As you mentioned in a comment, you\'re using log4j. I discovered (inadvertently) a place where I had written
LOG.error(exc);
instead of the typical
LOG.error(\"Some informative message\", e);
through laziness or perhaps just not thinking about it. The unfortunate part of this is that it doesn\'t behave as you expect. The logger API actually takes Object as the first argument, not a string - and then it calls toString() on the argument. So instead of getting the nice pretty stack trace, it just prints out the toString - which in the case of NPE is pretty useless.
Perhaps this is what you\'re experiencing?
回答3:
We have seen this same behavior in the past. It turned out that, for some crazy reason, if a NullPointerException occurred at the same place in the code multiple times, after a while using Log.error(String, Throwable)
would stop including full stack traces.
Try looking further back in your log. You may find the culprit.
EDIT: this bug sounds relevant, but it was fixed so long ago it\'s probably not the cause.
回答4:
Here is an explanation : Hotspot caused exceptions to lose their stack traces in production – and the fix
I\'ve tested it on Mac OS X
- java version \"1.6.0_26\"
- Java(TM) SE Runtime Environment (build 1.6.0_26-b03-383-11A511)
Java HotSpot(TM) 64-Bit Server VM (build 20.1-b02-383, mixed mode)
Object string = \"abcd\";
int i = 0;
while (i < 12289) {
i++;
try {
Integer a = (Integer) string;
} catch (Exception e) {
e.printStackTrace();
}
}
For this specific fragment of code, 12288 iterations (+frequency?) seems to be the limit where JVM has decided to use preallocated exception...
回答5:
exception.toString
does not give you the StackTrace, it only returns
a short description of this throwable.
The result is the concatenation of:
* the name of the class of this object
* \": \" (a colon and a space)
* the result of invoking this object\'s getLocalizedMessage() method
Use exception.printStackTrace
instead to output the StackTrace.
回答6:
Alternate suggestion - if you\'re using Eclipse, you could set a breakpoint on NullPointerException itself (in the Debug perspective, go to the \"Breakpoints\" tab and click on the little icon that has a ! in it)
Check both the \"caught\" and \"uncaught\" options - now when you trigger the NPE, you\'ll immediately breakpoint and you can then step through and see how exactly it is handled and why you\'re not getting a stack trace.
回答7:
toString()
only returns the exception name and the optional message. I would suggest calling
exception.printStackTrace()
to dump the message, or if you need the gory details:
StackTraceElement[] trace = exception.getStackTrace()
回答8:
(Your question is still unclear on whether your code is calling printStackTrace()
or this is being done by a logging handler.)
Here are some possible explanations about what might be happening:
The logger / handler being used has been configured to only output the exception\'s message string, not a full stack trace.
Your application (or some third-party library) is logging the exception using LOG.error(ex);
rather than the 2-argument form of (for example) the log4j Logger method.
The message is coming from somewhere different to where you think it is; e.g. it is actually coming some third-party library method, or some random stuff left over from earlier attempts to debug.
The exception that is being logged has overloaded some methods to obscure the stacktrace. If that is the case, the exception won\'t be a genuine NullPointerException, but will be some custom subtype of NPE or even some unconnected exception.
I think that the last possible explanation is pretty unlikely, but people do at least contemplate doing this kind of thing to \"prevent\" reverse engineering. Of course it only really succeeds in making life difficult for honest developers.
回答9:
This will output the Exception, use only to debug you should handle you exceptions better.
import java.io.PrintWriter;
import java.io.StringWriter;
public static String getStackTrace(Throwable t)
{
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw, true);
t.printStackTrace(pw);
pw.flush();
sw.flush();
return sw.toString();
}
回答10:
When you are using AspectJ in your project, it may happen that some aspect hides its portion of the stack trace. For example, today I had:
java.lang.NullPointerException:
at com.company.product.MyTest.test(MyTest.java:37)
This stack trace was printed when running the test via Maven\'s surefire.
On the other hand, when running the test in IntelliJ, a different stack trace was printed:
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)