JVM學習日記(十)Day10

G1回收器

這一篇是詳細說明G1回收器的,因為他相對來說確實是個縫合怪,上篇的內容又太多了所不清楚,所有這一篇進行詳細的說明,

第一個呢就是其實G1是兼顧并行和并發的,簡單來說就是既可以并行也可以并發,最大程度利用系統資源,在實現可達的最大吞吐量的前提下,盡可能的減少STW的時間,簡單的流程就是執行GC會先STW,然后多線程執行標記或者回收實現并行,然后切換回用戶線程,實現并發。

第二個就是分代分區的不同,上一篇主包有說過G1使用了分區算法把內存分成小的區域Region,但是分代其實和其他的回收器是不同的,他沒有像其他區一樣很嚴格的進行年輕代和老年代的劃分,如圖:

?他是先分區再分代的,也就是年輕代和老年代的區域可以不連續的,那同學就會問怎么執行標記整理?老年代不得亂套啊,其實不會的還是和之前一樣向起始地址移動。

第三種就是可預測的時間模型,因為采用了分區算法和分代算法,讓年輕代和老年代的區域更加的小了,G1可以根據各個需要回收的Region來進行價值排序任何放入列表優先回收(回收的空間和回收需要的時間)。這個就比較厲害了可以在相同的時間內比其他的回收器回收的效率更高,因為可以在不同的時間里選取最優的區域進行回收。

缺點就是內存的占用是比其他任何回收器都要高的多,這也是沒辦法要維護的表和屏障就比其他的多多了,因為是縫合怪的緣故所以推薦使用的內存就是6GB+使用G1。

G1回收器的參數設置

基礎參數:

  1. **-XX:+UseG1GC**?:啟用G1垃圾回收器(必備參數)。
  2. ?**-XX:MaxGCPauseMillis?:設置目標最大停頓時間(默認200ms)。G1會嘗試調整堆分區(Region)大小和回收策略以達到該目標,但不保證嚴格滿足**。這個和上面說的可預測時間模型是有關系的,如果設置的太短那么回收Region選擇的就會很少,如果設置的太大又會讓用戶覺得卡頓。
  3. ?**-XX:GCPauseTimeInterval**?:設置GC停頓的間隔時間目標(毫秒),與MaxGCPauseMillis配合使用。字面意思就是下一次GC相隔的時間。

?堆與Region配置?:

  1. ?**-XX:G1HeapRegionSize**?:設置Region大小(1MB~32MB,需為2的冪)。默認值由堆大小自動計算(所以到Region都是相同的,設置了后直到程序結束這個過程中Region的空間是不會改變的,另外G1回收器還有個Humongous區域就是存大對象的,超過1.5個Region就放在Humongous中,而這個H區是連續的不像R一樣分成很細的區域,不然一個大對象豈不是沒地方放了),大Region可減少碎片但可能增加停頓時間,小的話就是相反咯增加內存碎片但是減少停頓時間。
  2. ?**-XX:InitiatingHeapOccupancyPercent(IHOP)?**?:觸發并發標記周期的堆占用閾值(默認45%)。當內存占用超過此比例時,啟動混合GC。
  3. **-XX:G1ReservePercent**?:保留堆空間的百分比(默認10%),用于晉升失敗時的回退,避免Full GC。

?GC觸發與并行度?:

  1. **-XX:ConcGCThreads**?:并發標記階段的線程數(默認值基于CPU核心數)。過多線程可能影響應用吞吐量。
  2. ?**-XX:ParallelGCThreads**?:STW階段(如年輕代GC)的并行線程數,默認與CPU核心數相關。
  3. **-XX:G1MixedGCCountTarget**?:混合GC的預期回收次數(默認8次),控制老年代Region的回收節奏。
  4. ?**-XX:G1HeapWastePercent**?:允許的堆浪費比例(默認5%)。當可回收空間低于此值時,停止混合GC。

?還有很多的命令這邊就不一個一個去解釋介紹了,有興趣的小伙伴可以JVM實戰-G1參數調優 - 魚007 - 博客園自行查看了解。但是G1的設計初衷就是為了簡化JVM的調優,一般的調整只需要三步,啟用G1回收器,設置堆的最大內存,設置最大時間。

回收器和回收模式

不知道小伙伴還記不記得主包之前有提過的什么MinorGC、MajorGC、FullGC呢(JVM學習日記(二)Day2-CSDN博客)?那他們和主包上一篇講的7大GC有什么關系呢?

其實很好理解他們的關系就是回收器和回收模式,像MinorGC指的就是回收年輕代而Serial指的就是回收器,也就是MinorGC是所以年輕代GC的代名詞,而實際怎么去實現GC用什么算法是GC回收器決定的(這里提一下還有個MixedGC也就是混合GC,也是G1可以使用的,簡單來說就是同時回收年輕代和老年代,但是這個是部分回收,不像FullGC全部回收)。

記憶集與寫屏障

記憶集(Remembered Set, RSet)

每個Heap Region(內存分區)都有一個RSet,用于記錄其他Region中的對象對本Region的引用。例如:老年代Region A中的對象引用了年輕代Region B中的對象,則Region B的RSet會記錄這個引用關系(Rset記錄的是誰引用了我,而不是我引用了誰)。為什么需要RSet???G1是基于Region的分區回收器,回收時需要知道哪些Region是存活的(避免誤回收)。如果沒有RSet,每次回收一個Region時,需要掃描整個堆才能確定是否有其他Region引用它,效率極低。RSet讓G1可以只掃描相關Region,大幅減少GC工作量。sRSet如何實現??通常是一個哈希表或卡表(Card Table)?結構,存儲引用來源的Region或卡頁(Card)信息。例如:G1使用?“卡表”??(Card Table)來粗粒度記錄跨Region引用,再通過RSet細化管理。那什么又是卡表?將內存劃分為固定大小的卡頁,每個卡頁對于卡表中的一個標記位,簡單來說就是RegionA引用了RegionB中某一塊內存的對象,RegionA的Rset就會記錄這個被引用內存的卡頁。

寫屏障(Write Barrier)??

在對象引用被修改時觸發,記錄跨Region引用的變化到RSet。例如:當對象A(在Region 1)的字段被修改,指向對象B(在Region 2)時,寫屏障會更新Region 2的RSet。為什么需要寫屏障???在并發標記階段,用戶線程可能修改對象引用關系,導致標記結果不準確(漏標或誤標)。寫屏障通過捕獲引用變化,保證RSet和標記結果的正確性。寫屏障也分前/后寫屏障,簡單來說就是修改被引用對象的前/后修改引用他的Rset。

結構大概就是這樣子,這個的外R地址指的是外部Region的地址哦,這個ABCDE就是這個Region中存放的區塊。

外部Region地址臟卡頁索引實際引用位置
0x10000000Bitmap:?...0100Region 1的卡頁2(0x10001000)
0x30000000Bitmap:?...100000Region 3的卡頁5(0x30002800)

?G1回收器的回收階段

?

1. 年輕代GC(Young GC)??

?觸發條件?:Eden區Region占滿時觸發(STW)。快速回收年輕代(Eden + Survivor)。關鍵步驟?:

  1. ?初始標記(Initial Mark)??:短暫STW,標記GC Roots直接可達的對象(借Young GC執行)。
  2. ?根區域掃描(Root Region Scanning)??:掃描Survivor區中引用老年代的對象(需在下次Young GC前完成)。
  3. ?復制存活對象(Evacuation)??:并行將存活對象復制到Survivor區或晉升到老年代。
  4. ?調整Region分配?:根據MaxGCPauseMillis動態調整Eden/Survivor的Region數量。
2. 并發標記周期(Concurrent Marking Cycle)??
  • ?觸發條件?:老年代占用達到InitiatingHeapOccupancyPercent(默認45%)。標記全堆存活對象,為混合GC做準備。關鍵步驟?:
  1. ?初始標記(Initial Mark)??:短暫STW,標記GC Roots直接可達的對象(與Young GC共用)也就是先大概全堆標記一下確定范圍。
  2. ?并發標記(Concurrent Marking)??:短暫STW與用戶線程并發遍歷堆,標記存活對象。
  3. ?最終標記(Remark)??:短暫STW,處理并發標記期間遺漏的對象,可能上個階段并發的時候用戶線程又改變了部分對象,可能出現漏標。
  4. ?清理(Cleanup)??:統計Region存活數據,識別可回收Region(部分STW)。
?3. 混合回收(Mixed GC)??
  • ?觸發條件?:并發標記完成后啟動。回收年輕代 + 部分老年代Region(存活率低的Region優先)。?關鍵步驟?:
  1. ?選擇回收集(Collection Set)??:包含所有年輕代Region + 部分老年代Region(基于G1MixedGCLiveThresholdPercent,也就是對象存活率,默認65%當一個Region中存活的對象的內存占用小于這個Region的65%,這個區域會被優先收回)。
  2. ?復制存活對象(Evacuation)??:并行將存活對象復制到空閑Region(STW)。
  3. ?調整策略?:根據G1HeapWastePercent(允許可浪費空間,當可回收的垃圾小于這個默認值就不好采用混合GC)決定是否繼續混合回收。
?4.FULLGC

這個就不多說啦,就是內存不足的時候無法使用上面的GC了就會觸發這個最后的GC,退回到單線程的Serial Old GC(完全STW,長時間停頓)。

總結

本篇主要講的就是G1回收器,本篇內容比較多,大火們慢慢品哦。

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

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

相關文章

使用IP掃描工具排查網絡問題

隨著企業的發展,網絡中會新增各類設備,從臺式機、服務器到物聯網設備和虛擬機(VMs),所有這些設備都通過復雜的子網和虛擬局域網(VLAN)相連。 這種復雜性給 IT 團隊帶來了壓力,他們需…

Wireshark TS | 發送數據超出接收窗口

前言 來自于測試中無意發現到的一個接收窗口滿的案例,特殊,或者可以說我以前都沒在實際場景中見過。一開始都沒整太明白,花了些精力才算是弄清楚了些,記錄分享下。 問題說明 在研究擁塞控制的慢啟動階段時,通過 packet…

C語言自定義數據類型詳解(四)——聯合體

好的,接下來我們來學習最后一個自定義數據類型——聯合體。 一、什么是聯合體: 聯合體又叫共用體,用關鍵字union來進行定義。又因為所有的成員變量共用同一段內存空間(關于這一點,我們不久就會加以驗證)&…

[python][flask]Flask-Login 使用詳解

1. 簡介Flask-Login 是 Flask 的一個擴展,專門用于處理用戶認證相關的功能。它提供了用戶會話管理、登錄/注銷視圖、記住我功能等常見認證需求,讓開發者能夠快速實現安全的用戶認證系統。2. 安裝與基礎配置首先,需要安裝 Flask-Login&#xf…

【WebGPU學習雜記】WebAssembly中的relaxed_madd指令到底做了什么?

relaxed_madd 這條指令到底做了什么核心&#xff1a;relaxed_madd 是一個分量級別 (Component-wise) 的操作 首先&#xff0c;最重要的一點是&#xff1a;v128.relaxed_madd<f32>(a, b, c) 不是矩陣乘法。它是一個在三個向量 a, b, c 之間進行的、逐個分量的、并行的融合…

【全新上線】境內 Docker 鏡像狀態監控

境內 Docker 鏡像狀態監控&#xff1a;您的 Docker 加速伴侶 在當今云計算和容器化技術飛速發展的時代&#xff0c;Docker 已成為開發者不可或缺的工具。然而&#xff0c;對于身處國內的用戶而言&#xff0c;訪問境外 Docker Hub 等鏡像倉庫時常會遭遇網絡延遲和連接不穩定的困…

Visual Studio中部署PaddleOCRv5 (借助ncnn框架)

PaddleOCRv5_ncnn PaddleOCRv5 在Visual Studio中進行圖片OCR檢測&#xff08;ncnn框架open-mobile實現)&#xff0c;嘗試對nihui的ncnn-android-ppocrv5檢測算法的剝離與移植。 本項目Github鏈接如下&#xff1a;PaddleOCRv5_ncnn 寫在前面 本倉庫代碼是基于nihui的ncnn-a…

中級全棧工程師筆試題

解釋ACID特性&#xff0c;如何在node.js中實現事務操作針對React單頁應用&#xff0c;請提供至少5種性能優化方案&#xff0c;并解釋其原理&#xff1a; 減少首屏加載時間優化渲染性能資源加載策略狀態管理優化代碼分割方案 如何防止以下攻擊&#xff1a; JWT令牌挾持Graph QL查…

Windows---動態鏈接庫Dynamic Link Library(.dll)

DLL的“幕后英雄”角色 在Windows操作系統的生態中&#xff0c;有一類文件始終扮演著“幕后英雄”的角色——它們不像.exe文件那樣直接呈現為用戶可見的程序窗口&#xff0c;卻支撐著幾乎所有應用程序的運行&#xff1b;它們不單獨執行&#xff0c;卻承載著系統與軟件的核心功…

深入分析計算機網絡傳輸層和應用層面試題

三、傳輸層面試題&#xff08;Transmission Layer&#xff09;傳輸層位于 OSI 七層模型的第四層&#xff0c;它的核心任務是為兩個主機之間的應用層提供可靠的數據傳輸服務。它不僅承擔了數據的端到端傳輸&#xff0c;而且還實現了諸如差錯檢測、數據流控制、擁塞控制等機制&am…

【RH134 問答題】第 2 章 調度未來任務

目錄crontab 文件中的用戶作業時間格式怎么解釋&#xff1f;如果需要以當前用戶身份計劃周期性作業&#xff0c;在上午 8 點到晚上 9 點之間每兩分鐘一次輸出當前日期和時間&#xff0c;該作業只能在周一到周五運行&#xff0c;周六或周日不能運行。要怎么做&#xff1f;要計劃…

【ee類保研面試】通信類---信息論

25保研er&#xff0c;希望將自己的面試復習分享出來&#xff0c;供大家參考 part0—英語類 part1—通信類 part2—信號類 part3—高數類 part100—self項目準備 文章目錄**面試復習總綱****Chap2: 熵、相對熵和互信息 (Entropy, Relative Entropy, and Mutual Information)****…

vue2+node+express+MongoDB項目安裝啟動啟動

文章目錄 準備環境 安裝MongoDB 安裝 MongoDB Compass(圖形化數據庫管理工具) 安裝 Postman(接口測試工具) 項目結構 配置項目代理 項目啟動 提交項目 生成Access Token 準備環境 默認含有node.js、npm 安裝MongoDB 下載地址:https://www.mongodb.com/try/download/com…

JavaEE初階第十二期:解鎖多線程,從 “單車道” 到 “高速公路” 的編程升級(十)

專欄&#xff1a;JavaEE初階起飛計劃 個人主頁&#xff1a;手握風云 目錄 一、多線程案例 1.1. 定時器 一、多線程案例 1.1. 定時器 定時器是軟件開發的一個重要組件&#xff0c;是一種能夠按照預設的時間間隔或在特定時間點執行某個任務或代碼片段的機制。你可以把它想象成…

EDoF-ToF: extended depth of field time-of-flight imaging解讀, OE 2021

1. 核心問題&#xff1a;iToF相機的“景深”死穴我們之前已經詳細討論過&#xff0c;iToF相機的“景深”&#xff08;有效測量范圍&#xff09;受到光學散焦的嚴重制約。問題根源&#xff1a; 當iToF相機的鏡頭散焦時&#xff0c;來自場景不同深度的光信號會在傳感器像素上發生…

符號引用與直接引用:概念對比與實例解析

符號引用與直接引用&#xff1a;概念對比與實例解析 符號引用和直接引用是Java虛擬機(JVM)中類加載與執行機制的核心概念&#xff0c;理解它們的區別與聯系對于深入掌握Java運行原理至關重要。下面我將從定義、特性、轉換過程到實際應用&#xff0c;通過具體示例全面比較這兩類…

每日一講——Podman

一、概念1、定義與定位Podman&#xff08;Pod Manager&#xff09;是符合OCI標準的容器引擎&#xff0c;用于管理容器、鏡像及Pod&#xff08;多容器組&#xff09;。它無需守護進程&#xff08;Daemonless&#xff09;&#xff0c;直接通過Linux內核功能&#xff08;如命名空間…

Spring Boot DFS、HDFS、AI、PyOD、ECOD、Junit、嵌入式實戰指南

Spring Boot分布式文件系統 以下是一些關于Spring Boot分布式文件系統(DFS)的實現示例和關鍵方法,涵蓋了不同場景和技術的應用。這些示例可以幫助理解如何在Spring Boot中集成DFS(如HDFS、MinIO、FastDFS等)或模擬分布式存儲。 使用Spring Boot集成HDFS 基礎配置 // 配…

解決GoLand運行go程序報錯:Error: Cannot find package xxx 問題

問題描述 一個簡單的go程序&#xff0c;代碼如下 package mainimport "fmt" func main() {// 占位符&#xff0c;和java的String.format用法一樣fmt.Printf("我%d歲&#xff0c;我叫%s", 18, "yexindong") }結構如下當我想要運行時卻報錯 Error:…

Spring MVC設計精粹:源碼級架構解析與實踐指南

文章目錄一、設計哲學&#xff1a;分層與解耦1. 前端控制器模式2. 分層架構設計二、核心組件源碼解析1. DispatcherServlet - 九大組件初始化2. DispatcherServlet - 前端控制器&#xff08;請求處理中樞&#xff09;請求源碼入口&#xff1a;FrameworkServlet#doGet()請求委托…