Solve the problem of Java printing log swallowing exception stack

Original link: https://mazhuang.org/2023/06/26/java-swallow-stacktrace/

A few days ago, a classmate asked me to check a null pointer problem. When Java printed the log, the exception stack information was swallowed, which made it impossible to locate the problem.

Phenomenon

The code for catching exceptions and printing logs looks like this:

 try { // ... } catch ( Exception e ) { log . error ( "系统异常customerCode:{},data:{}" , customerCode , data , e ); // ... }

The logs found are as follows:

 2023-06-26 11:11:11.111 ERROR 1 --- [pool-1-thread-1] c.mazhuang.service.impl.TestServiceImpl : 系统异常customerCode:123,data:{"name":"mazhuang","age":18} java.lang.NullPointerException: null

The exception stack is lost.

analyze

It has been verified in a previous article that this writing method can print exceptions and stack information normally: Can the log that AI automatically completes print normally?

Confirmed again and again that there is no problem with the code writing, so I had to search for the keyword “Java exception stack loss” and found this article: The phenomenon and solution of Java exception stack loss . The problems mentioned here are similar to what we encountered. The same, and given the relevant instructions in Oracle’s official documentation:

https://www.oracle.com/java/technologies/javase/release-notes-introduction.html

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.

The general meaning is that in order to improve performance, the JVM will optimize some built-in exceptions. When these exceptions are thrown by a method multiple times, the JVM may recompile the method. At this time, it may use the method that does not provide stack information. Preallocation exception. If you want to completely disable pre-allocation exceptions, you can use the -XX:-OmitStackTraceInFastThrow parameter.

After learning this information, I flipped through the log since the last release of the service. Sure enough, the first dozen or so prints had exception stacks, and there were none later.

solution

  • Retrace the history log, find the normally printed stack information, locate and solve the problem;
  • You can also consider adding -XX:-OmitStackTraceInFastThrow parameter to the JVM parameter to disable optimization;

local reproduction

Write a simple program locally to reproduce it:

 public class StackTraceInFastThrowDemo { public static void main ( String [] args ) { int count = 0 ; boolean flag = true ; while ( flag ) { try { count ++; npeTest ( null ); } catch ( Exception e ) { int stackTraceLength = e . getStackTrace (). length ; System . out . printf ( "count: %d, stacktrace length: %d%n" , count , stackTraceLength ); if ( stackTraceLength == 0 ) { flag = false ; } } } } public static void npeTest ( Integer i ) { System . out . println ( i . toString ()); } }

When not adding -XX:-OmitStackTraceInFastThrow as a JVM parameter, the running results are as follows:

 ... count: 5783, stacktrace length: 2 count: 5784, stacktrace length: 2 count: 5785, stacktrace length: 0 Process finished with exit code 0

After I run this machine for five or six thousand times, the exception stack will be lost.

When adding -XX:-OmitStackTraceInFastThrow as a JVM parameter, the running results are as follows:

 ... count: 3146938, stacktrace length: 2 count: 3146939, stacktrace length: 2 count: 3146940, stacktrace length: Process finished with exit code 137 (interrupted by signal 9: SIGKILL)

Even after running for millions of times, the exception stack will not be lost, and the program can be terminated manually.

See the complete source code: https://github.com/mzlogin/java-notes/blob/master/src/org/mazhuang/StackTraceInFastThrowDemo.java

refer to

This article is transferred from: https://mazhuang.org/2023/06/26/java-swallow-stacktrace/
This site is only for collection, and the copyright belongs to the original author.