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

JVM 效能優化系列 (一):JVM 核心架構與記憶體模型總覽

     編輯:Java 相關知識

JVM 效能優化系列首篇:核心架構與記憶體模型

Java 應用程式運行在 JVM (Java Virtual Machine) 之上,深入理解 JVM 內部運作機制是進行效能調優、排查 OOM、分析 GC 行為的前提。本系列第一篇系統梳理 JVM 核心組件、類別載入機制、執行引擎、記憶體區域劃分與垃圾回收基礎,為後續調優實戰打下堅實基礎。

JVM 整體架構

JVM 架構圖

核心子系統

  1. 類別載入子系統:負責載入、連結、初始化 .class 檔案
  2. 執行引擎:解釋器 + JIT 編譯器 (C1/C2) + 垃圾收集器
  3. 運行時資料區:方法區、堆、Java 虛擬機棧、本地方法棧、程式計數器
  4. 原生介面:JNI 與作業系統/原生函式庫交互

運行時資料區詳細劃分 (JDK 8+)

區域線程共享性主要內容OOM 風險
堆全線程共享物件實例、陣列、字串常量池 (JDK 7+)高 - 主要調優目標
方法區全線程共享類別元資料、常量、靜態變數、JIT 編譯代碼
JDK 8+: Metaspace (本地記憶體)
中 - 類別過多/動態代理
Java 虛擬機棧線程私有棧幀 (局部變數表、操作數棧、動態連結、方法返回地址)低 - 遞歸過深/大量線程
本地方法棧線程私有Native 方法調用狀態低
程式計數器線程私有當前執行字節碼指令地址極低 - 唯一不會 OOM 區域

堆記憶體精細結構 (分代假設)

┌─────────────────────────────────────────────┐
│                   Heap                      │
├──────────────────┬──────────────────────────┤
│   Young Gen      │       Old Gen            │
│  (新生代)         │       (老年代)           │
│ ┌─────┬───┬───┐  │                          │
│ │Eden │S0 │S1 │  │  長期存活物件            │
│ │     │Sur│Sur│  │  大物件直接進老年代       │
│ └─────┴───┴───┘  │                          │
│   Minor GC       │       Major/Full GC      │
└──────────────────┴──────────────────────────┘
  • Eden 區:新物件優先分配區,大多數物件朝生夕死
  • Survivor 區 (S0/S1):Minor GC 後存活物件輪流複製,年齡計數器遞增
  • 老年代:經歷多次 GC 仍存活 (預設年齡 15) 或大物件直接進入
  • 分代假設:弱分代假設 (大多數物件生命週期短) + 強分代假設 (跨代引用較少)

類別載入機制

雙親委派模型

Bootstrap ClassLoader (啟動類載入器) - rt.jar, 核心庫
       ↑
Extension ClassLoader (擴充類載入器) - jre/lib/ext
       ↑
Application ClassLoader (應用類載入器) - classpath
       ↑
Custom ClassLoader (自訂類載入器) - 熱部署、模組化、加密類

優勢:避免類別重複載入、保護核心 API 不被篡改、隔離不同模組依賴版本

載入 → 連結 (驗證、準備、解析) → 初始化

  • 初始化觸發條件:new、getstatic/putstatic、invokestatic、反射、main 類、子類初始化觸發父類、動態語言支援

執行引擎與 JIT 編譯優化

關鍵優化技術

  • 方法內聯:將熱點小方法內聯到呼叫者,消除呼叫開銷
  • 逃逸分析:物件未逃逸則棧上分配、標量替換、同步消除
  • 去虛擬化:單一實作介面/最終方法直接內聯
  • 循環展開/向量化:利用 SIMD 指令集加速

垃圾回收基礎

判定存活算法

  • 可達性分析:從 GC Roots (棧帧局部變數、靜態屬性、常量、JNI 參考、同步鎖、類別載入器等) 向下搜尋
  • 四種引用類型:強引用 > 軟引用 (記憶體不足才回收) > 弱引用 (下次 GC 回收) > 虛引用 (僅用於追蹤回收)

經典 GC 算法

模式特點適用場景
解釋執行啟動快、無編譯開銷、逐條執行啟動階段、冷代碼、一次性代碼
C1 (Client Compiler)編譯快、優化較少、客戶端應用啟動敏感、GUI 應用
C2 (Server Compiler)編譯慢、深度優化、服務端應用長期運行、高吞吐、計算密集
分層編譯 (預設)0-4 層級:解釋 → C1 → C1+Profiling → C2平衡啟動速度與峰值效能
算法原理優點缺點適用區域
標記-清除標記存活 → 清除未標記實現簡單碎片化、效率低老年代
標記-整理標記存活 → 壓縮到一端無碎片需移動物件、更新引用老年代
複製劃分兩塊 → 存活複製到另一塊無碎片、分配快浪費 50% 空間新生代
分代收集新生代用複製、老年代用標記-整理綜合優勢複雜度高全堆

常見 JVM 啟動參數速查

# 堆記憶體
-Xms4g -Xmx4g              # 固定堆大小,避免震盪
-Xmn2g                     # 新生代大小 (隱含老年代 = 堆 - 新生代)

# Metaspace (JDK 8+)
-XX:MetaspaceSize=256m
-XX:MaxMetaspaceSize=512m

# GC 選擇
-XX:+UseG1GC               # G1 (JDK 9+ 預設)
-XX:+UseZGC                # ZGC (JDK 11+ 實驗/生產就緒)
-XX:+UseShenandoahGC       # Shenandoah (低延遲)

# GC 日誌 (JDK 9+ 統一日誌)
-Xlog:gc*:file=/logs/gc.log:time,uptime,level,tags:filecount=10,filesize=100m

# JIT 編譯
-XX:CompileThreshold=1000  # 觸發編譯的呼叫次數
-XX:+PrintCompilation      # 列印編譯資訊

# 除錯診斷
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/dumps/
-XX:ErrorFile=/logs/hs_err_pid%p.log

本系列後續主題預告

  1. 第二篇:GC 收集器詳細對比 (Serial、Parallel、CMS、G1、ZGC、Shenandoah)
  2. 第三篇:GC 日誌分析與調優實戰 (G1/Parallel 參數調整)
  3. 第四篇:JIT 編譯優化、逃逸分析、GraalVM 介紹
  4. 第五篇:記憶體洩漏排查 (MAT、JVisualVM、Arthas 實戰)
  5. 第六篇:生產環境 JVM 監控體系建設與容器化調優
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved