寻找缺少的堆栈跟踪
我們最近在博客中發(fā)表的一篇評論帶回了有關(guān)特定體驗的一些回憶。 我希望我沒有經(jīng)歷過的那種經(jīng)歷。 在我們創(chuàng)建Plumbr之前很長時間,我正在調(diào)試一個應(yīng)用程序,該應(yīng)用程序每次在藍月亮時都會給我一個例外。 詳細程度令人震驚:
就是這樣–沒有可使用的stacktrace。 而且該應(yīng)用程序由一個真正邪惡的系統(tǒng)管理員保護著,他不會讓我在部署后100碼之內(nèi)。 因此,為所有通宵人員準備了一個階段,他們試圖了解導致錯誤的原因。 我敢打賭,大多數(shù)讀者都知道我在這里說什么。 第一個嫌疑犯是顯而易見的。 暑期實習生從未真正獲得過異常處理,并且可以輕松地吞下異常,而無需重新拋出或正確記錄日志。 所以我期望在代碼中的某處找到這樣的東西:
System.out.println(e);但是,無論我對源代碼進行多徹底的檢查 ,都找不到類似這種粗心大意的東西。 從第二天起,除了每隔幾個小時接一個電話并提供“進度報告”,我就沒有多少回憶。 不幸的是,進展遙遙無期。 除非我想盡一切努力對生產(chǎn)進行大量更新,以使他們對可能的原因有一些更有意義的嘗試。 但是我確實記得當我開始懷疑我一直認為不可能的事情時,我對Java的信念。 也就是說,Java能夠從字面上吞噬您的Exception堆棧跟蹤。 實際上,JIT可以并且將會做到。 需要證明嗎? 運行以下代碼:
for (int i = 0; i < 100_000; i++) {try {args[0].toString();} catch (Exception e) {if (e.getStackTrace().length == 0) {System.out.format("Java ate my stacktrace after iteration #%d %n", i);break;}} } 在裝有最新穩(wěn)定JDK 7熱點的MB Pro中,異常堆棧跟蹤在迭代#12,288中被吞噬。 但是為什么在地球上會發(fā)生這種情況,又如何避免呢? 簡單的答案是,它是運行時期間應(yīng)用的JIT優(yōu)化之一。 正如我們最近發(fā)表的一篇文章所描述的那樣,創(chuàng)建Exceptions 非常昂貴 。 因此,出于性能目的,當JIT發(fā)現(xiàn)多次拋出異常時,可以重新編譯代碼。 重新編譯后,編譯器可以使用不提供堆棧跟蹤的預分配異常來選擇更快的策略。 希望你們中的絕大多數(shù)將永遠不必處理這種情況。 畢竟,當以觸發(fā)JIT切換到預分配的異常的速度創(chuàng)建異常時,您肯定在做其他錯誤。 畢竟,僅在例外情況下才應(yīng)發(fā)生例外。 但是對于那些這樣做的人,解決方案很簡單。 您可以通過將-XX:-OmitStackTraceInFastThrow添加到JVM啟動參數(shù)來禁用預分配的異常。 我也是,在下一次JVM重新啟動后找到了罪魁禍首。
翻譯自: https://www.javacodegeeks.com/2013/09/on-a-quest-for-missing-stacktraces.html
總結(jié)
- 上一篇: 平安富盈180收费吗?
- 下一篇: 支付宝国寿超月宝什么时候到期?