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

深入理解 JVM 虛擬機:運行時資料區、垃圾回收、類加載機制完整總結

     編輯:Java 綜合教學

JVM 核心知識體系總結

一、JVM 運行時資料區

JVM 將記憶體劃分為線程私有與線程共享兩大類:

區域屬性核心功能OOM 風險
程序計數器線程私有字節碼行號指示器,分支/迴路/線程恢復依賴此計數器無(規範中唯一不拋 OOM 的區域)
Java 虛擬機棧線程私有存放棧幀:局部變量表、操作數棧、動態連結、方法出口StackOverflowError(遞歸過深)、OOM(線程過多)
本地方法棧線程私有服務 Native 方法,功能與虛擬機棧類似同虛擬機棧
Java 堆線程共享物件實例分配主戰場,GC 主要管理區域,分代:新生代(Eden, S0, S1)、老年代OutOfMemoryError: Java heap space
方法區線程共享類資訊、常量、靜態變量、JIT 編譯代碼。JDK 1.7 常量池移至堆,JDK 1.8 元空間取代永久代OOM: Metaspace / PermGen space

堆記憶體細分與 GC 關係

+-----------------------+
|       老年代           |  <-- 大物件、長期存活物件
+-----------------------+
|     新生代             |
|  +---+---+---+        |
|  |Eden|S0 |S1 |        |  <-- Eden:S0:S1 = 8:1:1 (預設)
|  +---+---+---+        |
+-----------------------+

二、垃圾回收 (GC) 核心機制

1. 物件存活判定:可達性分析

從 GC Roots 為起點向下搜尋,無引用鏈相連的物件判定為可回收。

GC Roots 包含:

  • 虛擬機棧中引用的物件(局部變量表)
  • 方法區類靜態屬性引用的物件
  • 方法區常量引用的物件
  • 本地方法棧 JNI 引用的物件

2. 參考類型與回收策略

3. 三大經典 GC 演算法

參考類型回收時機應用場景
強引用永不回收普遍物件引用
軟引用記憶體不足前快取(圖片、網路資料)
弱引用GC 運行時快取、監聽器、ThreadLocal
虛引用不影響生命週期追蹤物件被回收時機(如直接記憶體釋放)

4. 分代收集理論

  • 弱分代假設:絕大多數物件「朝生夕死」
  • 強分代假設:熬過越多次 GC 的物件越難死
  • 新生代:Minor GC 頻繁、速度快、回收率高(複製演算法)
  • 老年代:Major/Full GC 耗時長、頻率低(標記-整理/標記-清除)

三、類加載機制

1. 類生命週期:七個階段

加載 → 驗證 → 準備 → 解析 → 初始化 → 使用 → 卸載
           ↑                    ↑
        固定順序           解析可在初始化後(支援動態綁定)

2. 類初始化觸發條件(僅 5 種)

  1. new、getstatic、putstatic、invokestatic 指令(新建物件、讀寫靜態欄位、呼叫靜態方法)
  2. java.lang.reflect 反射調用
  3. 初始化子類時,父類未初始化
  4. JVM 啟動指定主類(含 main)
  5. JDK 7+ MethodHandle 解析為靜態欄位/方法句柄

3. 不會觸發初始化的場景

  • 子類引用父類靜態欄位(只觸發父類初始化)
  • 陣列定義引用類(SuperClass[] sca = new SuperClass[10])
  • 常量在編譯期進入調用者常量池(ConstClass.HELLO_WORLD)

4. 類加載器與雙親委派模型

          啟動類加載器 (Bootstrap)  ← C++ 實現,載入 rt.jar 核心庫
                    ↑
          擴展類加載器 (Extension)  ← 載入 jre/lib/ext/*.jar
                    ↑
          應用類加載器 (Application)  ← 載入 CLASSPATH,預設加載器
                    ↑
          自定義類加載器 (Custom)  ← 使用者繼承 ClassLoader 實現

雙親委派核心邏輯:收到載入請求先委派父加載器,父無法載入時子才嘗試。
優勢:避免重複載入、保護核心類不被篡改(沙箱安全)。

5. 熱部署與 OSGi 核心:打破雙親委派

  • Tomcat:WebappClassLoader 優先自行載入,再委派父加載器(隔離 Web 應用類庫)
  • OSGi:模組化類加載器網狀結構,支援多版本共存、動態安裝/卸載

四、實戰排查指南

演算法核心思想優點缺點應用場景
標記-清除標記可回收 → 統一清除實現簡單效率低、產生記憶體碎片老年代
複製劃分兩塊,存活物件複製到另一塊無碎片、分配快浪費 50% 空間新生代 (Eden + Survivor)
標記-整理標記 → 存活物件向一端移動無碎片移動開銷大老年代
問題排查工具/命令關鍵動作
響應緩慢jstack、jmap、Arthas、Async Profiler分析線程狀態、鎖爭用、CPU 熱點
頻繁 Full GCjstat -gc、GC 日誌、GCEasy、Arthas分析老年代佔用、大物件直接進老年代、記憶體洩漏
OOMjmap -heap、MAT、JVisualVM、heap dump分析支配者樹、洩漏疑點、歷史堆對比

核心工具鏈:
jps → jstack → jmap → jhat/MAT → jstat → Arthas/Async Profiler
建議建立標準化排查 SOP,從現象 → 定位 → 根因 → 修復 → 驗證 → 沉澱。

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