1问题 NULL Exception 的堆栈信息,不是总是有完整的堆栈信息,有的时候没有,如何解决呢?见下面代码。
public class NullExceptionTest {
static final Logger logger = Logger.getLogger(FileUpload.class);
public static void main(String[] args) {
int youcount = 0;
int wucount = 0;
for(int i = 0; i < 100000; i++){
String a = null;
try{
a.toLowerCase();
} catch (Exception e){
if(e.getStackTrace().length == 0) {
System.out.println(e.getStackTrace().length);
System.out.println(e.getStackTrace());
wucount++;
} else{
youcount++;
}
}
}
System.out.println("youcount"+youcount);
System.out.println("wucount"+wucount);
}
}
重点是 这句号
since our isolated example code above indicated that initial exceptions would throw with the full stack trace, we went back into older logs and grepped. 第一次报Null exceptions一定是有完成的堆栈信息的,找到就行了。
Today I was working with Kumar and Elian where we encountered production logs with dozens of NullPointerExceptions with no stack trace. We identified that the JIT compiler will optimize away stack traces in certain exceptions if they happen enough. The code below reproduces it. We are on jdk 1.6 (I don’t remember the minor version now).
Run it as follows and the issue will appear (the stack trace length changes from 2 to 0):javac NpeThief.java && java -classpath . NpeThief
javac NpeThief.java && java -server -classpath . NpeThief
How to fix it? The following options resolve it and it stays at 2, never going to 0 as length of NPE’s stack trace:javac NpeThief.java && java -XX:-OmitStackTraceInFastThrow -server -classpath . NpeThief
javac NpeThief.java && java -XX:-OmitStackTraceInFastThrow -classpath . NpeThief
javac NpeThief.java && java -Xint -classpath . NpeThief
javac NpeThief.java && java -Xint -server -classpath . NpeThief
So the solution is to start with -XX:-OmitStackTraceInFastThrow argument to java which instructs the JIT to remove this optimization [1,2], or operate in interpreted only mode [3]. What is going on? [2]
The JVM flag -XX:-OmitStackTraceInFastThrow disables the performance optimization of the JVM for this use case. If this flag is set, the stacktrace will be available. (editor: or if the -Xint is set).
“The compiler in the server VM now provides correct stack backtraces for all “cold” built-in exceptions. For performance purposes, when such an exception is thrown a few times, the method may be recompiled. After recompilation, the compiler may choose a faster tactic using preallocated exceptions that do not provide a stack trace. To disable completely the use of preallocated exceptions, use this new flag: -XX:-OmitStackTraceInFastThrow.”http://java.sun.com/j2se/1.5.0/relnotes.html
How does this impact performance? I did extremely naive timing and time java [args] -classpath . NpeThief. It behaved as expected, with interpreted the slowest. Is that the solution?
No. We weren’t going to change production JVM options to resolve this, insteadsince our isolated example code above indicated that initial exceptions would throw with the full stack trace, we went back into older logs and grepped. Sure enough, right after we deployed there were exceptions appearing with the full stack trace. That gives us enough information where we can identify and fix the bug.
Notes:
[1] Related sun bug 4292742 NullPointerException with no stack trace
[2] Helpful StackOverflow discussion of NullPointerException missing stack traces
[3] -Xint: Operate in interpreted-only mode. Compilation to native code is disabled, and all bytecodes are executed by the interpreter. The performance benefits offered by the Java HotSpot VMs’ adaptive compiler will not be present in this mode.