1. 程式人生 > >log日誌中不列印異常棧的具體資訊

log日誌中不列印異常棧的具體資訊

問題與分析

最近在查專案的log時發現報了大量的NPE(NullPointerException),詭異的是隻log了Exception的類名,卻沒有具體的堆疊資訊,以致於無法對該NPE異常進行準確定位。

這是因為jvm自身存在著優化機制,但一個同樣的異常重複出現並被列印到log後,jvm可以不提供具體的堆疊資訊來提高效能。關於這個的具體資訊我們可以從官網上查到相關的資料:

http://www.oracle.com/technetwork/java/javase/relnotes-139183.html#vm

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.

谷歌翻譯如下:

伺服器VM中的編譯器現在為所有“冷”內建異常提供正確的堆疊回溯。出於效能目的,當丟擲這樣的異常幾次時,可以重新編譯該方法。重新編譯之後,編譯器可以使用不提供堆疊跟蹤的預分配異常來選擇更快的策略。要完全禁用預分配的異常,請使用以下新標誌:-XX:-OmitStackTraceInFastThrow。

解決方案

有兩個解決方案,第一個是安裝官網說的,可以通過設定jvm的啟動引數來關閉該策略:

-XX:-OmitStackTraceInFastThrow

另一個解決方案是不設定啟動引數,直接重新啟動伺服器,比如Tomcat。重啟伺服器時jvm被重新啟動,這樣再遇到同樣的Exception時就會打印出來,當然如果後續如果重複遇到同樣的Exception還是無法打印出具體的異常棧資訊。

當時我是選擇了後者這個方案,因為如果啟用了該引數會導致log日誌太過龐大,也降低了效能,直接重啟伺服器,並快速定位bug以便於解決問題。