說說你對JVM的垃圾回收機制的理解?

Java 虛擬機(JVM)的垃圾回收(Garbage Collection,GC)機制是自動管理內存的核心,其核心目標是識別并回收不再被使用的對象所占用的內存,避免內存泄漏和溢出。以下從垃圾判斷方法垃圾回收算法具體垃圾收集器三個層面詳細說明:

一、垃圾判斷方法:如何識別 "垃圾" 對象

垃圾回收的前提是判斷哪些對象已經不再被使用(即 "垃圾")。JVM 主要采用兩種判斷方式:

1. 引用計數法(Reference Counting)
  • 原理:每個對象維護一個 "引用計數器",當對象被引用時計數器 + 1,引用失效時 - 1;當計數器為 0 時,認為對象是垃圾。
  • 優點:實現簡單,判斷效率高。
  • 缺點:無法解決循環引用問題(如 A 引用 B,B 引用 A,兩者計數器均不為 0,但實際已無外部引用)。
  • 現狀:Java 虛擬機未采用這種方式(因循環引用問題),Python 等語言使用。
2. 可達性分析算法(Reachability Analysis)
  • 原理:以 "GC Roots" 為起點,通過引用鏈遍歷對象;若對象無法通過任何引用鏈連接到 GC Roots,則被判定為垃圾。
  • GC Roots:指一系列 "根對象",包括:
    • 虛擬機棧(棧幀中的局部變量表)中引用的對象;
    • 方法區中類靜態屬性引用的對象;
    • 方法區中常量引用的對象;
    • 本地方法棧中 JNI(Native 方法)引用的對象。
  • 優點:解決了循環引用問題,是 Java 虛擬機的核心判斷方式。
  • 擴展:Java 中的 "引用" 被細分為 4 種類型(強引用、軟引用、弱引用、虛引用),不同引用類型影響對象被回收的時機(如軟引用在內存不足時才會被回收)。

二、垃圾回收算法:如何回收垃圾

確定垃圾對象后,需要通過具體算法回收其內存。常見的基礎算法包括:

1. 標記 - 清除算法(Mark-Sweep)
  • 步驟
    1. 標記:通過可達性分析標記所有存活對象(非垃圾);
    2. 清除:遍歷堆內存,回收所有未被標記的對象(垃圾)。
  • 優點:實現簡單,無需移動對象。
  • 缺點
    • 效率低:標記和清除過程都需要遍歷整個堆,耗時較長;
    • 內存碎片:回收后會產生大量不連續的內存碎片,可能導致大對象無法分配內存。
2. 標記 - 復制算法(Mark-Copy)
  • 步驟
    1. 將堆內存分為大小相等的兩塊(如 A 和 B),僅使用 A 塊;
    2. 標記:標記 A 塊中的存活對象;
    3. 復制:將 A 塊中所有存活對象復制到 B 塊(按順序連續放置);
    4. 清除:清空 A 塊,后續內存分配僅使用 B 塊(下次回收時交換角色)。
  • 優點
    • 效率高:復制存活對象的成本低于清除大量垃圾;
    • 無內存碎片:存活對象連續放置,內存分配簡單(指針碰撞即可)。
  • 缺點
    • 內存利用率低:僅能使用一半內存;
    • 不適合存活對象多的場景(復制成本高)。
  • 適用場景:Java 新生代(因新生代對象存活時間短,存活對象少)。
3. 標記 - 整理算法(Mark-Compact)
  • 步驟
    1. 標記:標記所有存活對象;
    2. 整理:將所有存活對象向內存一端移動,按順序排列;
    3. 清除:直接清除邊界外的所有內存(垃圾)。
  • 優點:解決了標記 - 清除的內存碎片問題,且內存利用率 100%。
  • 缺點:整理階段需要移動對象,成本較高(尤其是老年代對象存活時間長,移動成本大)。
  • 適用場景:Java 老年代(因老年代對象存活時間長,存活對象多,需避免碎片)。
4. 分代收集算法(Generational Collection)
  • 原理:根據對象存活周期將堆內存分為新生代老年代,針對不同區域采用不同算法(結合上述基礎算法的優勢):
    • 新生代:對象存活時間短(朝生夕死),適合標記 - 復制算法(只需復制少量存活對象);
    • 老年代:對象存活時間長(存活概率高),適合標記 - 清除或標記 - 整理算法(避免頻繁移動對象)。
  • 細節:新生代進一步分為 Eden 區(80%)和兩個 Survivor 區(From、To 各 10%),分配對象時先在 Eden 區,回收時將存活對象復制到 Survivor 區,多次存活后進入老年代。
  • 現狀:幾乎所有 Java 虛擬機都采用分代收集算法作為基礎框架。

三、垃圾收集器:算法的具體實現

垃圾收集器是垃圾回收算法的具體實現,不同收集器針對不同場景(如吞吐量、延遲)優化。Java 虛擬機中常見的收集器包括:

1. Serial GC(串行收集器)
  • 特點:單線程執行垃圾回收,回收時暫停所有用戶線程("Stop The World",STW)。
  • 算法
    • 新生代:標記 - 復制;
    • 老年代:標記 - 整理。
  • 優點:實現簡單,內存占用少,適合單核 CPU 環境。
  • 缺點:STW 時間長,不適合多線程、大堆內存應用。
  • 適用場景:客戶端應用(如桌面程序),JVM 默認客戶端模式下的收集器。
2. ParNew GC(并行新生代收集器)
  • 特點:Serial GC 的多線程版本,僅作用于新生代,老年代仍需配合 Serial Old 或 CMS。
  • 算法:新生代采用標記 - 復制(多線程并行標記和復制)。
  • 優點:利用多 CPU 加速新生代回收,減少 STW 時間。
  • 缺點:仍有 STW,老年代若配合 Serial Old 會導致長停頓。
  • 適用場景:多 CPU 環境下的服務端應用,常作為 CMS 收集器的新生代搭檔。
3. Parallel Scavenge GC(并行清除收集器)
  • 特點:注重吞吐量(吞吐量 = 用戶代碼執行時間 /(用戶代碼時間 + GC 時間)),屬于 "吞吐量優先" 收集器。
  • 算法
    • 新生代:標記 - 復制(多線程并行);
    • 老年代:Parallel Old(標記 - 整理,多線程并行)。
  • 優點:可自動調節 GC 參數(如新生代大小、晉升老年代閾值)以追求最高吞吐量。
  • 缺點:STW 時間可能較長,不適合對延遲敏感的應用。
  • 適用場景:后臺計算(如數據分析)等對吞吐量要求高、可接受一定停頓的場景。
4. CMS(Concurrent Mark Sweep,并發標記清除)
  • 特點:以低延遲為目標,盡可能減少 STW 時間,老年代收集器(需配合 ParNew 作為新生代收集器)。
  • 步驟(核心是 "并發",即 GC 線程與用戶線程同時執行):
    1. 初始標記:標記 GC Roots 直接關聯的對象(STW,時間短);
    2. 并發標記:從初始標記的對象出發,遍歷引用鏈(與用戶線程并發,無 STW);
    3. 重新標記:修正并發標記期間因用戶線程操作導致的引用變化(STW,時間較短);
    4. 并發清除:回收所有未標記的對象(與用戶線程并發,無 STW)。
  • 優點:并發收集,STW 時間短,適合對延遲敏感的應用(如 Web 服務)。
  • 缺點
    • CPU 敏感:并發階段會占用 CPU 資源,影響用戶線程;
    • 內存碎片:基于標記 - 清除算法,老年代易產生碎片;
    • 需預留內存:并發清除時用戶線程仍在分配內存,需保證內存不耗盡。
  • 現狀:JDK 9 中被標記為 deprecated,JDK 14 中移除,被 G1 等收集器替代。
5. G1(Garbage-First)
  • 特點:區域化分代式收集器,兼顧吞吐量和延遲,適用于大堆內存(如 4GB 以上)。
  • 內存布局:將堆分為多個大小相等的 Region(1MB~32MB),每個 Region 可動態標記為新生代(Eden/Survivor)或老年代,無需物理隔離。
  • 核心思想:優先回收 "垃圾最多的 Region"(Garbage-First),減少 GC 時間。
  • 步驟
    1. 初始標記:標記 GC Roots 直接關聯的對象(STW);
    2. 并發標記:遍歷引用鏈,計算每個 Region 的垃圾占比(與用戶線程并發);
    3. 最終標記:修正并發標記的偏差(STW,使用 SATB 算法高效處理);
    4. 篩選回收:根據 Region 的垃圾占比排序,優先回收垃圾多的 Region(多線程并行,STW,采用標記 - 復制算法避免碎片)。
  • 優點
    • 靈活處理大堆內存,延遲可控(可設置最大 STW 時間);
    • 無內存碎片(篩選回收時采用復制算法)。
  • 適用場景:JDK 9 及以上默認收集器,適合中大型應用(如服務器、云原生應用)。
6. 低延遲收集器(ZGC、Shenandoah)
  • ZGC(JDK 11 引入):

    • 目標:STW 時間不超過 10ms,支持 TB 級堆內存。
    • 特點:基于 Region,采用 "著色指針" 和 "讀屏障" 技術,幾乎全程并發(僅初始標記和最終標記有極短 STW)。
  • Shenandoah(OpenJDK 引入,非 Oracle JDK 默認):

    • 目標:低延遲,支持大堆。
    • 特點:采用 "并發整理" 算法,在并發階段移動對象(通過轉發指針和寫屏障實現),幾乎無 STW。
  • 適用場景:對延遲要求極高的應用(如高頻交易、實時數據處理)。

總結

Java 虛擬機的垃圾回收機制是一個 "判斷垃圾 - 選擇算法 - 具體實現" 的完整體系:

  • 通過可達性分析判斷垃圾對象;
  • 基于分代思想,結合標記 - 清除、復制、整理等基礎算法;
  • 不同垃圾收集器(如 Serial、CMS、G1、ZGC)針對吞吐量、延遲等不同目標優化,需根據應用場景選擇。

實際開發中,需通過監控工具(如 JConsole、VisualVM)分析 GC 日志,選擇合適的收集器并調優參數(如堆大小、新生代比例),以平衡性能需求。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/94213.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/94213.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/94213.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

兌換汽水瓶

實現代碼:public static void main(String[] args) {Scanner in new Scanner(System.in);while (in.hasNextInt()) {int n in.nextInt();if (n 0) {break;}System.out.println(n / 2);}}

結合 Flutter 和 Rust 的跨平臺開發方案

結合 Flutter 和 Rust 的跨平臺開發方案 1. 核心思想 本方案的核心思想是Flutter 負責 UI,Rust 負責邏輯 。Flutter 作為一個成熟的 UI 框架,專注于渲染流暢、跨平臺一致的用戶界面。而將那些對性能、安全和并發有高要求的復雜業務邏輯、計算密集型任務或底層系統操作,全部…

理想汽車智駕方案介紹 2|MindVLA 方案詳解

一、引言 MindVLA 主要包括空間智能模塊、語言智能模塊、動作策略模塊、強化學習模塊,這些模塊分別有以下功能: 空間智能模塊:輸入為多模態傳感器數據,使用 3D 編碼器提取時空特征,然后將所有傳感器與語義信息融合成…

計算機網絡基礎(三) --- TCP/IP網絡結構(運輸層)

運輸層1. 概述和運輸服務運輸層協議為運行在不同主機上的應用進程之間提供了邏輯通信功能, 運輸層協議是在端系統中而不是路由器中實現的, 網絡應用程序可以調用多種運輸層協議, 如因特網的兩種協議: TCP 和 UDP ,每種協議都能為調用的應用程序提供一組不同的運輸層服務1.1 運輸…

JdbcTemplate和MyBatis的區別

在 Java 后端開發中,JdbcTemplate(Spring 框架提供)和 MyBatis(持久層框架)都是用于簡化數據庫操作的工具,但它們的設計理念、使用方式、靈活性和適用場景有顯著差異。下面從核心定位、核心特性、使用方式、…

埃氏篩|樹dfs|差分計數

lc525把數組里的0換成-1&#xff0c;求子數組和為零的最長長度用哈希表記錄前綴和首次出現的位置通過找相同前綴和的位置差得出最長的0和1數量相等的子數組長度。class Solution { public:int findMaxLength(vector<int>& nums) {unordered_map<int,int>hashta…

(JVM)Java 對象創建的完整過程

在日常開發和面試中&#xff0c;經常會被問到 “Java 中對象是如何被創建的&#xff1f;” 表面上只是一個 new 關鍵字&#xff0c;但 JVM 在幕后完成了一系列復雜操作。 可以總結為以下 六大步驟&#xff1a;類加載檢查 → 分配內存 → 內存清零 → 設置對象頭 → 執行構造函數…

數據庫優化提速(三)JSON數據類型在酒店管理系統搜索—仙盟創夢IDE

在 MySQL 中&#xff0c;JSONB 類型&#xff08;MySQL 中實際為 JSON 類型&#xff0c;功能類似 PostgreSQL 的 JSONB&#xff0c;支持高效的 JSON 數據存儲和查詢&#xff09;非常適合存儲半結構化數據&#xff0c;例如酒店入住客人的復雜信息&#xff08;包含客人基本信息、入…

小程序全局狀態管理:使用MobX進行跨組件數據共享詳解(九)

一、定義全局數據共享&#xff08;又叫&#xff1a;狀態管理&#xff09;是為了解決組件之間數據共享的問題&#xff1b;全局數據共享方案&#xff1a;VueX、Redux、MobX等&#xff1b;二、小程序全局數據共享方案使用mobx-miniprogram配合mobx-miniprogram-bindings實現全局數…

生成模型 | DDPM -> Imrpoved DDPM -> DDIM

DDPM: Denoising Diffusion Probabilistic Models 采樣過程中的迭代計算為&#xff1a; xt?11αt(xt?1?αt1?αˉ?θ(xt,t))β~tzx_{t-1} \frac{1}{\sqrt{\alpha_t}}(x_t - \frac{1 - \alpha_t}{\sqrt{1 - \bar{\alpha}}}\epsilon_{\theta}(x_t, t)) \sqrt{\tilde{\beta…

Linux驅動之DMA(三)

目錄一、驅動內容1. 核心結構體解析2. 關鍵模塊解析3. 驅動初始化流程4. 關鍵寄存器操作5. 典型工作流程6. 代碼特點7. 重要函數列表8. 使用示例二、驅動中DMA的使用1. DMA通道初始化&#xff08;imx_uart_dma_init&#xff09;2. DMA發送流程&#xff08;imx_uart_dma_tx&…

MongoDB 分片集群把非分片集合轉成分片集合

記得關注一下博主&#xff0c;博主每天都會更新IT技術&#xff0c;讓你有意想不到的小收獲哦^_^ 文章目錄*記得關注一下博主&#xff0c;博主每天都會更新IT技術&#xff0c;讓你有意想不到的小收獲哦^_^*一、MongDB集群啟停止1、MonogoDB分片集群服務啟動順序(三臺主機都要操作…

mybatis過渡到mybatis-plus過程中需要注意的地方

將 MyBatis 升級為 MyBatis-Plus&#xff08;簡稱 MP&#xff09;是一個平滑過渡的過程&#xff0c;因為 MP 是 MyBatis 的增強工具&#xff08;而非替代&#xff09;&#xff0c;但仍有一些關鍵注意事項需要關注&#xff0c;以確保升級后功能兼容且能充分利用 MP 的特性&#…

openEuler系統中如何將docker安裝在指定目錄

在 openEuler 中&#xff0c;Docker 的默認數據存儲目錄為 /var/lib/docker&#xff08;程序文件通常安裝在系統默認路徑&#xff0c;一般無需修改&#xff09;。若需將 Docker 數據&#xff08;鏡像、容器、卷等&#xff09;存儲到指定目錄&#xff0c;可通過修改 Docker 配置…

2.4 我國金融市場的監管體制

1、國務院金融發展委員會職責 2、中國人民銀行職責

PHP - 實例屬性訪問與靜態方法調用的性能差異解析

觀察到了一個看似矛盾的現象&#xff1a;實例屬性訪問更快&#xff0c;但靜態方法調用更快。這實際上是兩種不同的操作&#xff0c;下面我將詳細解釋其中的原理和差異。1. 實例屬性訪問為什么快訪問機制class MyClass {public $instanceProp 1; }$obj new MyClass(); $value …

音視頻面試題集錦第 31 期

音視頻面試題集錦第 31 期&#xff1a; 1、I 幀、P 幀和 B 幀的概念及區別&#xff1f;2、視頻編碼中的碼率控制技術有哪些&#xff1f;3、音頻采樣參數有哪些&#xff1f;4、RTMP 和 HLS 協議各有什么特點&#xff1f;如何選擇&#xff1f;5、WebRTC 中的 ICE、STUN、TURN 各…

企業視頻庫管理高效策略

內容概要本文全面探討企業視頻庫管理的高效策略&#xff0c;旨在幫助組織優化視頻資源處理。首先&#xff0c;我們將介紹企業視頻庫管理的基本概念和核心價值。接著&#xff0c;深入分析智能分類核心技術如何通過AI算法實現視頻自動歸類。之后&#xff0c;闡述云集成實現路徑&a…

WebSocket和跨域問題

WebSocket 特點 WebSocket 是一種在單個 TCP 連接上進行全雙工通信的協議。簡單來說&#xff0c;它就像是在客戶端和服務器之間建立了一條"專用通道"&#xff0c;雙方可以隨時主動發送消息給對方&#xff0c;而不需要像HTTP那樣總是由客戶端發起請求。 同一時間、雙向…

微服務-19.什么是網關

一.網關曾經我們的項目是單體項目&#xff0c;前端只需要請求8080端口&#xff0c;就可以獲取所有需要的數據和服務并進行渲染。但是拆分成微服務后&#xff0c;會面臨幾大問題&#xff1a;1.但是現在我們將該單體項目拆分成了微服務項目&#xff0c;每個項目都有自己獨立的端口…