面對 1.2~1.3 GB 堆上限的 32 位元 Windows 胖客戶端,商業剖析工具(JProfiler、YourKit 等)因額外記憶體開銷導致 JVM 崩潰,無法完成剖析。團隊轉向極簡剖析策略:使用單一 C 檔案實作的 heapprofile(基於 JVMPI),零運行時開銷,僅在觸發堆傾印時遍歷堆將「物件大小 + 類別名」寫入檔案,不在記憶體建立任何中間結構。
剖析流程
- 以最小配置啟動 heapprofile,應用正常運行至目標狀態。
- 觸發堆傾印(產生 ~1 GB 原始文字檔),耐心等待 I/O 完成。
- 解析輸出:統計各類別物件數量與總大小,鎖定佔用最大的類別。
- 對鎖定類別重新編譯,在建構子植入堆疊追蹤(建立
new Exception() 取得堆疊),重新部署收集分配點分布。
- 發現大量可移除物件(如重複快取、未清理監聽器),並優化必要物件結構(壓縮、共享),釋放 ~200 MB。
關鍵技術點
- heapprofile:Matthias Ernst 開發,極簡、零開銷、適合超大堆環境。
- 堆疊追蹤植入法:在建構子 `new Exception()` 取得分配點,彙總相同堆疊計數,儲存極少字串即可定位熱點。
- 時間尺度預估:1 GB 文字傾印需數分鐘,切勿誤判為卡死而重複觸發導致崩潰。
心得
「大師使用任何能用的工具」。當標準工具失效,回歸基礎原理、接受簡陋但有效的手段,才能拿到關鍵資料並完成調優。雖最終仍未瘦身到能跑完整剖析器,但邊緣剖析證明了無工具也能調優的可能性。