【Java】垃圾回收學習筆記(二):分代假說與垃圾回收算法

文章目錄

  • 0. 分代收集理論
    • 分代假說
    • 分代GC定義
  • 1. 垃圾回收算法
    • 1.1 標記清除(Mark-Sweep)算法
      • 優點
      • 缺點
    • 1.2 標記復制算法
      • 優點
      • 缺點
      • 為什么是8:1:1?
    • 1.3 標記整理算法
      • 優點
      • 缺點
  • 2. 是否移動?
  • Reference

0. 分代收集理論

分代假說

現在多數JVM GC都遵循分代收集(Generational Collection)理論,其中涉及三個經驗性的分代假說:

  1. 弱分代假說(Weak Generational Hypothesis):絕大多說對象都是朝生夕滅
    1. 對象創建先進入新生代(Young/Nursery),進行較為頻繁、局限于新生代的Minor GC
  2. 強分代假說(Strong Generational Hypothesis):熬過越多次垃圾收集過程的對象,越難以消亡
    1. 對象經過幾輪gc后進入老年代(Old/Tenured),進行次數相對少、局限于老年代的Major GC
  3. 跨代引用假說(Intergenerational Reference Hypothesis):跨代引用相對于同代引用來說占比極少
    1. 跨代引用:比如新生代對象可能被老年代所引用,所以Minor GC時需要在固定的GC Roots外,再額外增加老年代中的Roots來保證可達性分析的正確性(young引用old同理)。
    2. 以新生代被老年代引用為例,根據跨代引用假說,如果遍歷整個老年代的引用關系來增加GC Roots,效率將會非常低,可以通過在新生代增加專門的數據結構(記憶集,Rememered),來標識跨代引用關系。比如,CMS和G1垃圾收集器都會通過寫前屏障的方式,將跨代引用記錄在卡表(可以看做一種記憶集)中。

分代GC定義

前面有提到Minor GC、Major GC之類的說法,其實就是不同分代中的GC行為,類似的定義包括:

  • 部分收集(Partial GC): 不完整收集整個Java堆的GC。又分為:
    • 新生代收集(Minor GC/Young GC):目標是新生代的GC
    • 老年代收集(Major GC/Old GC):目標是老年代的GC。目前只有CMS收集器會有只針對老年代的GC。
    • 混合收集(Mixed GC):目標是整個新生代部分老年代的GC。目前只有G1收集器會有Mixed GC。
  • 整堆收集(Full GC):整個Java堆和方法區的GC。

1. 垃圾回收算法

1.1 標記清除(Mark-Sweep)算法

將垃圾回收分為標記和清除兩個階段:

  1. 標記階段:標記出所有活躍對象(或者標記死亡對象)
  2. 清除階段:回收未被標記為活躍的對象(或者標記死亡的對象)

在這里插入圖片描述

優點

實現簡單、速度快。后面的收集算法大多在此基礎上改進得來的。

缺點

  • 執行效率不穩定:標記、清除的執行效率隨對象數增加而降低;
  • 清除后可能造成內存碎片:如果new了一個大的對象,碎片化的內存沒法使用,造成內存浪費。

1.2 標記復制算法

將內存分為兩個區域:一個區域用于存儲存活對象,一個保留區域

  1. 標記處所有存活對象,移動到保留區域
  2. 移動到保留區域的對象進行內存整理(避免碎片化)
  3. 將原有區域整個清理掉,變成新的保留區域

在這里插入圖片描述

現代的商用Java虛擬機大多采用改進的標記復制算法來進行新生代GC。

優點

效率很高,不會產生內存碎片

缺點

  • 對象存活率較高時,需要很多復制操作,效率降低。比如老年代中,大部分對象存活周期都很長(前面提到過的強分代假說),所以老年代中一般不采用標記-復制算法。
  • 保留區域與存活區域1:1(半區復制,Semispace Copying)的話,會有一半內存被浪費。

一些現代的垃圾收集器(ParNew等)中將新生代分為Eden區+2個Survive(Survivor)區(8:1:1,Appel式回收)解決內存浪費:new對象先分配到Eden中,將Eden與非保留區域的survivor1標記后,將存活對象移動到作為保留區域的Survivor2中,將其他區域(Eden與Survivor1)GC,survivor1成為新的保留區域。

為什么是8:1:1?

大家都知道新生代對象的壽命大部分都很短,也就是弱分代假說中的“朝生夕滅”。IBM公司有研究對對象的“朝生夕滅”做了量化,即新生代對象中98%熬不過第一輪GC。因此完全沒必要按照1:1分配新生代空間。

HotSpot虛擬機默認的Eden與Survivor比例是8:1,可以保證每次新生代可用內存空間為整個新生代的90%(Eden 80%+非保留區域survivor的10%)。

但可能存在多于10%對象存活的情況。因此,當一次Minor GC后,Survivor空間不足以容納幸存的對象,就需要老年代作為保底。

1.3 標記整理算法

  • 標記階段:標記存活對象,清除垃圾對象。
  • 整理階段:內存整理,讓存活對象向內存空間的一端移動。

在這里插入圖片描述

優點

  • 相比于標記-復制算法,內存使用效率高,吞吐量高;
  • 同時也不會有標記-清除算法的內存碎片化問題。

這里吞吐量的定義為:運行用戶代碼時間/(運行用戶代碼時間+運行垃圾收集時間)

缺點

  • 消耗時間比較長,高并發場景可能影響系統性能

大家應該多少都聽說過“Stop The World ”,也就是移動存活對象時(特別是老年代每次回收都有大量對象存活,需要大量移動操作),移動操作必須暫停用戶應用程序。因此有時候老年代空間不足或內存碎片化過于嚴重(大對象內存申請不了),導致Full GC,就會面臨STW的困境。如果想要減少STW的次數,可以適當增加新生代的比例,即大部分對象生命周期在新生代快速流轉,可以適當減少老年代的STW。

標記-清除算法也要停頓用戶線程,但是時間相對較短

2. 是否移動?

標記-清除算法跟其他兩個算法最本質的區別,在于它沒有移動操作,也因此存在內存碎片化的問題。當然,即使不移動,內存碎片化也不是沒有解決辦法,只能依賴更復雜的內存分配器和內存訪問器來解決。但是內存訪問是用戶程序最頻繁的操作之一,如果增加額外負擔,會影響吞吐量。

可見:

  • 移動對象:內存回收會更加復雜,GC停頓時間較長,但吞吐量會更劃算;
  • 不移動對象:內存分配時會更加復雜,GC停頓時間更短,但內存分配的額外操作會極大影響吞吐量。

因此,HotSpot虛擬機中,關注吞吐量的Parallel Scavenge收集器給予標記-整理算法,關注延遲的CMS(老年代)基于標記-清除算法(實際上CMS都會用,大多數時間標記-刪除,等碎片化道影響大對象分配時,標記-整理一次)。

最新的ZGC和Shenandoah收集器使用讀屏障是愛你整理過程和用戶線程的并發執行

Reference

《深入理解java虛擬機:JVM高級特性與最佳時間(第3版)》 周志明

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

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

相關文章

Navicat和MySQL的安裝

1、下載 Navicat Navicat 官網:www.navicat.com.cn/ 在產品中可以看到很多的產品,點擊免費試用 Navicat Premium 即可,是一套多連數據庫開發工具,其他的只能連接單一類型數據庫 點擊試用 選擇系統直接下載 二、安裝 Navicat 安…

代碼江湖:Python 中的進程與線程

大家好,我是闊升。今天,咱們來聊聊 Python 中的兩個"老熟人"——進程和線程。這兩個概念可以說是 Python 多任務編程中的"雙子星",既相似又不同,讓不少小伙伴們頭疼不已。不過別擔心,今天我們就來…

element el-table實現表格動態增加/刪除/編輯表格行,帶校驗規則

本篇文章記錄el-table增加一行可編輯的數據列,進行增刪改。 1.增加空白行 直接在頁面mounted時對form里面的table列表增加一行數據,直接使用push() 方法增加一列數據這個時候也可以設置一些默認值。比如案例里面的 產品件數 。 mounted() {this.$nextTi…

latex 使用 thanks 首頁空白 問題

寫IEEE journal的時候遇到的問題……用latex寫了\thanks,編譯的論文第一頁是空的,這是因為\thanks要在\author內部,然后再用\maketitle,即\author{… \thanks{}}。這樣的話詳細信息就會出現在論文首頁的左下角 另外,\…

linux創建定時任務

crontab方式 先查看是否有cron systemctl status crond 沒有的話就安裝 yum install cronie 打開你的crontab文件進行編輯。使用以下命令打開當前用戶的crontab文件: crontab -e * * * * * /export/test.sh >> /export/test.log 2>&1/export/test.s…

差分算法中的F 和CR參數

自查使用。。F 類似梯度的大小 兩者都用于種群中新個體的生成

leetcode--從中序與后序遍歷序列構造二叉樹

leeocode地址:從中序與后序遍歷序列構造二叉樹 給定兩個整數數組 inorder 和 postorder ,其中 inorder 是二叉樹的中序遍歷, postorder 是同一棵樹的后序遍歷,請你構造并返回這顆 二叉樹 。 示例 1: 輸入:inorder …

Unity插件 Unitask學習日志

Unity插件 Unitask學習日志 下載地址 https://github.com/Cysharp/UniTask點擊這里可以查閱中文文檔 在Unity 2020,2021 中使用UPM下載會找不到,可以使用2022版本的unity可以在upm中找到。 安裝方式: 下載zip之后解壓, 復制Plugins 到Uni…

uniapp小程序使用webview 嵌套 vue 項目

uniapp小程序使用webview 嵌套 vue 項目 小程序中發送 <web-view :src"urlSrc" message"handleMessage"></web-view>export default {data() {return {urlSrc: "",};},onLoad(options) {// 我需要的參數比較多 所以比較臃腫// 獲取…

01. 數組篇(進行中......)

一. 前綴和技巧 &#xff08;1&#xff09;前綴和 前綴和技巧適用于快速、頻繁地計算一個索引區間內的元素之和。 class NumArray { public:vector<int> preSum; //前綴和數組NumArray(vector<int>& nums) {//preSum[0] 0&#xff0c;便于計算累加和preSum…

Qt圖形編輯類使用總結—正在編輯中

Qt的圖形編輯通常會涉及以下三個類:QGraphicsView類、QGraphicsScene類及QGraphicsItem類。 QGraphicsView 是構建復雜圖形用戶界面的強大工具,尤其適用于那些需要動態更新、可交互的2D圖形化應用程序,如圖表繪制、流程圖編輯器、游戲地圖顯示等等。通過結合使用 QGraphics…

Spring中的工廠模式詳解及應用示例

1. Spring中的BeanFactory BeanFactory是一個接口&#xff0c;表示它是一個工廠&#xff0c;負責生產和管理bean。在Spring中&#xff0c;BeanFactory是IOC容器的核心接口&#xff0c;定義了管理Bean的通用方法&#xff0c;如 getBean 和 containsBean。 BeanFactory與IOC容器…

Python編程:如何有效等待套接字的讀取與關閉

背景介紹 網絡編程是現代應用程序開發的重要組成部分&#xff0c;尤其是在大數據和實時通信的背景下。套接字&#xff08;Socket&#xff09;作為網絡通信的核心技術&#xff0c;是開發網絡應用程序的基礎。在Python編程中&#xff0c;如何有效地等待套接字的讀取與關閉事件是…

柔性測斜儀:監測鉆孔位移的核心利器

柔性測斜儀&#xff0c;作為一款創新的測量工具&#xff0c;憑借其卓越的設計與性能&#xff0c;在地下建筑、橋梁、隧道及水利水電工程等領域展現出非凡的應用價值。其安裝便捷、操作簡便、高精度及長壽命等特性&#xff0c;使之成為監測鉆孔垂直與水平位移的理想選擇。以下是…

算力共享,分布式大模型是什么,模型并行,流水線并行

目錄 算力共享,分布式大模型是什么 一、算力共享 二、分布式大模型 AllReduce是什么 原理概述 具體原理 簡單例子 模型并行,流水線并行是什么 模型并行 流水線并行 環形通信(如Ring AllReduce)、樹形通信(如Tree AllReduce 環形通信(Ring AllReduce) 樹形通…

【ComfyUI的API接口調用示例】

ComfyUI的API接口調用示例 本文目的 本文調用接口示例主要指導需要調用ComfyUI的開發者如何調用ComfyUI官方的API接口提交任務、查詢歷史、獲取繪畫視頻結果等。 閱讀本文的前提是你本地已經安裝了ComfyUI&#xff0c;并且對工作流繪畫和生成視頻已經有所了解。注意如圖右邊欄…

arm架構安裝chrome

在ARM架構設備上安裝谷歌軟件或應用通常涉及到幾個步驟&#xff0c;這取決于你要安裝的具體谷歌產品&#xff0c;比如谷歌瀏覽器、Google Play服務或者是其他谷歌開發的軟件。下面我會給出一些常見的指導步驟&#xff0c;以安裝谷歌瀏覽器為例&#xff1a; 在Linux ARM64上安裝…

常用的三角函數公式

sin ? 2 x cos ? 2 x 1 \sin ^2 x \cos ^2 x 1 sin2xcos2x1 tan ? x sin ? x cos ? x \tan x \dfrac{\sin x}{\cos x} tanxcosxsinx? cot ? x 1 tan ? x cos ? x sin ? x \cot x \dfrac{1}{\tan x}\dfrac{\cos x}{\sin x} cotxtanx1?sinxcosx? sec …

零基礎做項目---五子棋對戰---day02

用戶模塊 完成注冊登錄&#xff0c;以及用戶分數管理~使用數據庫來保存上述用戶信息. 使用 MyBatis來連接并操作數據庫了 主要步驟: 1.修改 Spring的配置文件,使數據庫可以被連接上. 2.創建實體類&#xff0c;用戶, User 3.創建Mapper接口~ 4.實現MyBatis 的相關xml配置…

MySQL安全值守常用語句

一、用戶權限設置 1、Mysql中用戶是如何定義的 用戶名主機域 10.0.0.5110.0.0.%%10.0.0.0/255.255.255.0Db01Localhost127.0.0.1 2、用戶創建 create user xinjing% identified by 123 3、用戶刪除 drop user username&#xff1b;username 是要刪除的用戶名:如 drop user root…