Java 開發者常誤以為「有 GC 就不用管記憶體」。實則 JVM 進程記憶體遠不止 Heap:尚含 bytecode、JIT 編譯碼、Native 代碼、Thread Stack、Metaspace、共享 DLL 等。Windows 虛擬記憶體機制(分頁、提交、保留、工作集、駐留集)更讓數字解讀充滿陷阱。本文整理免費工具鏈,教你精準掌握 Java 進程真實記憶體畫像。
Windows 記憶體模型速覽
- 虛擬位址空間:32 位程序 2 GB 用戶空間,分頁大小 4 KB。
- 三種頁面狀態:Free(未用)、Reserved(預留,如
-Xmx 上限)、Committed(已獲分頁檔支援,可實際讀寫)。
- 工作集 vs 駐留集:工作集 = 邏輯上「為避免分頁必須駐留」的頁面;駐留集 = 當前真正在物理記憶體的頁面。Task Manager 的「Mem Usage」實為駐留集,且含共享頁,不可直接相加。

內建工具:Task Manager & PerfMon
| 指標 | 來源 | 含義 | 備註 |
| Mem Usage | Task Manager | 駐留集(含共享頁) | 不可跨進程相加 |
| VM Size | Task Manager | 已提交私有虛擬記憶體 | 接近 Committed Bytes |
| Working Set | PerfMon (Process) | 駐留集 | 同 Mem Usage |
| Private Bytes | PerfMon (Process) | 已提交私有虛擬記憶體 | 同 VM Size |
| Virtual Bytes | PerfMon (Process) | 整個虛擬位址空間大小 | 含 Reserved,通常遠大於前兩者 |
| Page Faults/sec | PerfMon (Process) | 每秒分頁錯誤率 | 持續高值暗示記憶體壓力 |


進階免費工具鏈
1. PrcView — 視覺化位址空間映射
- 右鍵進程 → Memory Map,可見 Free/Reserved/Committed 區塊。
- Java Heap 表現為:小塊 Committed + 巨大 Reserved 區域(
-Xmx 上限)。
- 底部統計:Private(私有提交)、Mapped(記憶體映射檔)、Image(EXE/DLL 代碼)。


2. TopToBottom — 可搜尋的記憶體瀏覽器
- Memory 分頁僅顯示 Committed 區,但標記更豐富:Thread Stack、Process Heap、Environment、TEB 等。
- 支援文字/十六進位搜尋,適合追蹤物件參考或緩衝區內容。
- Modules 分頁列出所有 DLL、載入順序、相依關係、共享進程列表。


3. VADump — 命令列級深度轉儲
vadump -o -p > dump.txt
-o 產生「工作集快照」:逐頁列出駐留頁屬於 Heap、Stack、DLL、Mapped Data 等類別。
- 尾部摘要表:
Heap(Windows 進程堆)、Other Data(含 Java Heap)、Code/StaticData(DLL 代碼段)。
- 模組貢獻表:精確到每個 DLL 佔用多少 Private/Shareable/Shared 頁。
- 堆/堆疊貢獻細分至段落位址範圍,利於定位 Native 記憶體洩漏。

4. Sysinternals 套件
- Process Explorer:Task Manager 強化版,支援 DLL/Handle 檢視、即時圖表、替換預設管理員。
- ListDLLs:
listdlls -r 輸出 DLL 基址、大小、路徑,含重定位資訊。
- Handle:
handle -a -p 列出所有 Handle(檔案、執行緒、Semaphore、Key、Section…),計數暴增提示洩漏。
實戰技巧與避坑指南
- 找 PID:Task Manager → Applications → 右鍵 → Go To Process。
- 辨識 Java 進程:TopToBottom Startup 分頁可見完整命令列(含
-Xmx、Classpath)。
- 共享記憶體實測:啟動兩個同樣 JVM,對比 VADump
Code/StaticData 的 Shared 變化,驗證 DLL 共享效益。
- 最小化視窗觀察 Working Set 縮減:Windows 會主動修剪非前台進程工作集,非洩漏。
- ClearMem (Win2003/NT):強制佔滿物理記憶體再釋放,逼迫進程釋放非必要頁面,測量「最小必要駐留集」。
- PermGen / Metaspace OOM:大量第三方 JAR 導致類元資料超限,啟動參數加
-XX:MaxPermSize=512m (Java 7) 或 -XX:MaxMetaspaceSize=512m (Java 8+)。
總結
工具無銀彈,關鍵在於「理解指標定義」與「組合交叉驗證」:
- Heap 壓力 →
-verbose:gc / JConsole / VisualVM / Arthas。
- Native/Metaspace/Thread Stack → VADump
-o + PrcView + TopToBottom。
- DLL 共享/載入異常 → ListDLLs / Process Explorer。
- Handle/檔案洩漏 → Handle / Process Explorer。
掌握這套免費工具鏈,即可在無商業授權環境下完成 90% 的 Java 記憶體診斷任務。