首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

JVM 運行時記憶體結構深度解析:堆、棧、方法區、垃圾回收與參數調優

     編輯:Java 綜合教學

JVM 運行時記憶體結構深度解析

全面剖析 JVM 記憶體模型、垃圾回收機制、收集器實作、核心調優參數,以及堆與棧的本質差異。

1. JVM 記憶體模型

運行時記憶體分為共享內存區(全線程共享)與線程內存區(線程私有)。

1.1 共享內存區

持久帶:HotSpot 實現方法區,存放類資訊、方法、常量池。可用 -XX:PermSize、-XX:MaxPermSize 設定(JDK 8 後改為 Metaspace)。

堆:物件實例主要儲存區,分代管理:

  • Young Space:Eden + S0 + S1(Survivor 區,8:1:1)。新物件優先分配在 Eden。
  • Old Space:長期存活物件晉升區。

JVM 記憶體結構圖

1.2 線程內存區

每個線程獨有:PC Register(指令計數器)、JVM 棧、本地方法棧。

JVM 棧以棧幀為單位,每個方法調用對應一個棧幀,包含:

  • 局部變量表:以數組儲存基本型別與引用,long/double 佔兩槽。
  • 操作數棧:運算暫存區,入棧/出棧操作。
  • 幀資料區:常量池指標、方法返回/異常處理資訊。

棧幀結構

基於棧 vs 基於寄存器指令集

HotSpot 使用基於棧指令集(跨平台、程式碼緊湊),Dalvik/ART 使用基於寄存器(指令少、執行快)。最終均轉為 CPU 組合語言執行。

2. 垃圾回收機制

2.1 為何需要 GC

自動偵測並釋放無用記憶體,提高利用率,開發者無需手動釋放。

2.2 回收區域

專注於共享區:**堆**與**持久帶**(方法區)。線程區隨線程銷毀自動釋放。

2.3 物件存活判定

  • 引用計數法:簡單但無法解決循環引用,JVM 不採用。
  • 可達性分析(GC Roots):從 GC Roots 出發搜尋,不可達物件判定為可回收。
    GC Roots 包含:虛擬機棧引用、方法區靜態屬性/常量引用、本地方法棧 JNI 引用、JVM 內部特殊物件。

GC Roots 可達性分析

不可達物件經歷兩次標記:mark1 進入 Finalizer 隊列執行 finalize(),若復活則移除標記;mark2 確認最終回收。finalize() 僅執行一次,物件只有一次復活機會。

2.4 垃圾回收演算法

演算法原理優點缺點適用區域
標記-清除標記後直接釋放基礎簡單記憶體碎片多Old Space 基礎
標記-複製將存活物件複製到另一塊記憶體無碎片、分配快可用記憶體減半Young Space (Eden + Survivor)
標記-整理清除後將存活物件壓縮到一端無碎片、空間利用高需移動物件、耗時Old Space

標記-清除 標記-複製 標記-整理

2.5 分代收集策略

  • Minor GC:Young Space 觸發,頻繁、快,採用標記-複製。物件在 Survivor 區熬過閾值(預設 15 歲)晉升 Old。
  • Full GC:Old + Perm 回收,較慢,採用標記-整理。觸發條件:Old 滿、Perm 滿、System.gc()、動態策略變化。

2.6 常見收集器

  • Serial / Serial Old:單線程,停頓長,適合單核 Client 模式。
  • ParNew / Parallel Scavenge / Parallel Old:多線程並行,Parallel 關注吞吐量。
  • CMS:並發標記-清除,追求低停頓,但產生碎片。
  • G1 (JDK 7+):面向全堆,標記-整理,可預測停頓,逐代替 CMS。

3. JVM 核心調優參數

參數說明
-Xmx / -Xms最大/初始堆大小
-XX:NewSize / -XX:MaxNewSize新生代大小
-XX:PermSize / -XX:MaxPermSize持久帶大小 (JDK 8-)
-XX:NewRatio新生代:老年代 比例 (如 2 表示 1:2)
-XX:SurvivorRatioEden:Survivor 比例 (預設 8:1)
-Xss單線程棧大小 (JDK 5+ 預設 1M)
-XX:+PrintGCDetails輸出詳細 GC 日誌

Client vs Server 模式

  • -client:啟動快,C1 輕量編譯器,適合桌面應用。
  • -server:啟動慢,C2 激進優化編譯器,長期運行效能高,適合伺服端。
  • JDK 5+ 自動偵測:2 CPU + 2GB 以上預設 Server;64 位 JDK 僅支援 Server。
  • 可修改 jvm.cfg 強制指定模式。

4. 堆 vs 棧 本質差異

  • 棧:執行單位,存基本型別與引用,線程私有,生命週期隨方法。
  • 堆:儲存單位,存物件實例,全線程共享,GC 管理。

Java 參數傳遞只有「傳值」:基本型別傳值副本;引用型別傳引用地址副本。修改引用指向的物件內容可見,但無法改變呼叫端的引用本身。

參數傳遞記憶體圖解

5. 附圖彙總

JVM 記憶體總覽

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved