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

Java 內存模型與垃圾回收深度解析:運行時數據區、對象存活判定與 GC 算法演進

     編輯:Java 相關知識

JVM 運行時數據區

Java 虛擬機在執行程式時將管理的內存劃分為若干區域(JDK 1.8+ 元空間取代永久代):

區域線程共享性核心功能
程式計數器私有當前執行字節碼指令地址
Java 虛擬機棧私有棧幀:局部變量表、操作數棧、動態連接、方法出口
本地方法棧私有服務 Native 方法
Java 堆共享對象實例分配主戰場,GC 主戰場,分代:新生代/老年代
方法區共享類信息、常量、靜態變量、JIT 編譯代碼(1.8+ 元空間)
運行時常量池共享方法區一部分,存編譯期常量與符號引用,String.intern() 操作此處

對象存活判定:可達性分析算法

主流 JVM 採用可達性分析(非引用計數,避免循環引用問題):

  • 從 GC Roots 出發向下搜索,走過的路徑稱「引用鏈」。
  • 對象到 GC Roots 無引用鏈相連 → 標記為可回收。

GC Roots 包含

  1. 虛擬機棧中引用的對象(局部變量表)
  2. 方法區中類靜態屬性引用的對象
  3. 方法區中常量引用的對象
  4. 本地方法棧中 JNI 引用的對象

四種引用類型與生命週期

引用類型強度回收時機典型應用
強引用最強永不回收Object obj = new Object()
軟引用次強記憶體不足前回收緩存(SoftReference)
弱引用較弱下次 GC 即回收緩存、監聽器(WeakReference)
虛引用最弱不影響生命週期,回收前收到通知直接內存管理(PhantomReference)

經典 GC 算法演進

1. 標記-清除

兩階段:標記存活 → 清除未標記。缺點:效率低、產生大量內存碎片。

2. 複製算法

內存劃分為大小相等兩塊,每次用一塊,存活對象複製到另一塊,再清理已用半區。優點:無碎片、分配簡單(指針碰撞)。缺點:內存利用率仅 50%。
→ 現代新生代優化:Eden : Survivor = 8:1:1,僅浪費 10% Survivor 空間。

3. 標記-整理

標記後將存活對象向一端移動,清理邊界外內存。適用於老年代(存活率高、不適合複製)。

4. 分代收集

根據對象生命週期劃分區域,針對性選算法:

  • 新生代:朝生夕死 → 複製算法(Eden + 2 Survivor)
  • 老年代:存活率高 → 標記-整理

對象自我拯救

finalize() 可在 GC 首次標記後、第二次標記前執行一次「自救」(重新建立引用)。但:

  • 優先級極低,執行時間不確定。
  • 每個對象僅有一次機會。
  • 已被 Deprecated(JDK 9+),建議用 Cleaner / PhantomReference 替代。

總結

理解 JVM 內存劃分、可達性分析、引用類型與分代算法,是排查 OOM、優化 GC、設計緩存體系的理論基石。

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