G1 垃圾收集器

从 JDK1.9 开始默认 G1,应用在多处理器和大容量内存环境中。

基础概念

Region

G1 给整一块Heap内存区域均匀等分了N个 Region,N 默认情况下是 2048。
Region的大小只能是1M、2M、4M、8M、16M或32M (1-32M,并且为2的指数),比如-Xmx16g -Xms16g,G1就会采用16G / 2048 = 8M 的Region。

G1 的常用参数很简单,主要有下面几个

  1. -XX:+UseG1GC:为开启G1垃圾收集器
  2. -Xmx32g:堆内存的最大内存为32G
  3. XX:MaxGCPauseMillis=200: 设置GC的最大暂停时间为200ms
  4. -XX:G1HeapRegionSize: 设置每个region大小

一般的调优手段是修改最大暂停时间。同时,如果能预测到项目中大对象比较多,可以设置较大的region值。

在这里插入图片描述

H 表示 Humongous,大的对象,当分配的对象大于等于Region大小的一半的时候就会被认为是巨型对象。
H对象默认分配在老年代,可以防止GC的时候大对象的内存拷贝。
通过如果发现堆内存容不下H对象的时候,会触发一次GC操作。

SATB

全称是 Snapshot At The Beginning,是GC开始时活着的对象的一个快照。它是通过 Root Tracing 得到的,作用是维持并发GC的正确性。

三色标记算法

可达性分析进一步延伸出三色标记法。通常,GC 算法会维持一套对象图,图上节点表示对象,节点之间的连线表示对象间的引用关系,其中:

  • 白色节点:尚未被标记的对象;
  • 黑色节点:已经被垃圾收集器访问过,且这个对象的引用全部被扫描过;
  • 灰色节点:已经被垃圾收集器访问过,且这个对象至少还有一个引用没被扫描;

RSet

由于并发标记期间,用户线程和GC线程是并发的,可能出现白对象漏标的情况。漏标发生有两个前提:

  1. 用户线程赋值了一个黑对象到该白对象的引用
  2. 用户线程删除了所有灰对象到白对象的引用

例如当垃圾扫描器扫描到下面的情况的时候:

在这里插入图片描述

这时候应用程序执行了以下操作:

A.c=C
B.c=null

这样,对象的状态图变成如下情形:

在这里插入图片描述

这时候垃圾收集器再标记扫描的时候就会下图成这样:
在这里插入图片描述

很显然,此时C是白色,被认为是垃圾需要清理掉,显然这是不合理的。那么我们如何保证应用程序在运行的时候,GC标记的对象不丢失呢?有如下2中可行的方式:

  1. 在插入的时候记录对象
  2. 在删除的时候记录对象

刚好这对应CMS和G1的2种不同实现方式:

CMS采用的是 写屏障+增量更新(Incremental update)

在CMS采用的是增量更新(Incremental update),只要在写屏障(write barrier)里发现要有一个白对象的引用被赋值到一个黑对象的字段里,那就把这个白对象变成灰色的。即插入的时候记录下来。

G1采用的是 SATB(snapshot-at-the-beginning),pre-write barrier 解决这个问题。简单说就是在并发标记阶段,当引用关系发生变化的时候,通过 pre-write barrier 函数会把这种这种变化记录并保存在一个队列里,在JVM源码中这个队列叫satb_mark_queue。在remark阶段会扫描这个队列,通过这种方式,旧的引用所指向的对象就会被标记上,其子孙也会被递归标记上,这样就不会漏标记任何对象,snapshot的完整性也就得到了保证。

引用 R 大的话

其实只需要用pre-write barrier把每次引用关系变化时旧的引用值记下来就好了。这样,等concurrent marker到达某个对象时,这个对象的所有引用类型字段的变化全都有记录在案,就不会漏掉任何在snapshot里活的对象。当然,很可能有对象在snapshot中是活的,但随着并发GC的进行它可能本来已经死了,但SATB还是会让它活过这次GC。CMS的incremental update设计使得它在remark阶段必须重新扫描所有线程栈和整个young gen作为root;G1的SATB设计在remark阶段则只需要扫描剩下的satb_mark_queue ,解决了CMS垃圾收集器重新标记阶段长时间STW的潜在风险。

SATB的方式记录活对象,也就是那一时刻对象snapshot, 但是在之后这里面的对象可能会变成垃圾, 叫做浮动垃圾(floating garbage),这种对象只能等到下一次收集回收掉。在GC过程中新分配的对象都当做是活的,其他不可达的对象就是死的。

在Region中通过 top-at-mark-start(TAMS)指针,分别为 prevTAMS 和 nextTAMS 来记录新配的对象。示意图如下:

在这里插入图片描述

在TAMS以上的对象就是新分配的,因而被视为隐式marked。

G1的concurrent marking用了两个bitmap: 一个prevBitmap记录第n-1轮concurrent marking所得的对象存活状态。由于第n-1轮concurrent marking已经完成,这个bitmap的信息可以直接使用。 一个nextBitmap记录第n轮concurrent marking的结果。这个bitmap是当前将要或正在进行的concurrent marking的结果,尚未完成,所以还不能使用。

其中top是该region的当前分配指针,[bottom, top)是当前该region已用(used)的部分,[top, end)是尚未使用的可分配空间(unused)。

  1. [bottom, prevTAMS): 这部分里的对象存活信息可以通过prevBitmap来得知
  2. [prevTAMS, nextTAMS): 这部分里的对象在第n-1轮concurrent marking是隐式存活的
  3. [nextTAMS, top): 这部分里的对象在第n轮concurrent marking是隐式存活的
  • G1 Mixed GC

混合回收。之所以叫混合是因为回收所有的年轻代的Region+部分老年代的Region。

G1的强大之处在于他有一个停顿预测模型(Pause Prediction Model),他会有选择的挑选部分Region,去尽量满足停顿时间。

Mixed GC的触发也是由一些参数控制。比如 XX:InitiatingHeapOccupancyPercent 表示老年代占整个堆大小的百分比,默认值是45%,达到该阈值就会触发一次Mixed GC。

Mixed GC主要可以分为两个阶段:

  1. 全局并发标记(global concurrent marking)
    全局并发标记又可以进一步细分成下面几个步骤:

a. 初始标记(initial mark,STW)。它标记了从GC Root开始直接可达的对象。初始标记阶段借用young GC的暂停,因而没有额外的、单独的暂停阶段。
b. 根区域扫描(root region scan)。G1 GC 在初始标记的存活区扫描对老年代的引用(扫描CardTable和RSet),并标记被引用的对象。该阶段与应用程序(非STW)同时运行,并且只有完成该阶段后,才能开始下一次STW年轻代垃圾回收。
c. 并发标记(Concurrent Marking)。这个阶段从GC Root开始对heap中的对象标记,标记线程与应用程序线程并行执行,并且收集各个Region的存活对象信息。过程中还会扫描上文中提到的SATB write barrier所记录下的引用。
d. 最终标记(Remark,STW)。标记那些在并发标记阶段发生变化的对象,将被回收。
e. 清除垃圾(Cleanup,部分STW)。这个阶段如果发现完全没有活对象的region就会将其整体回收到可分配region列表中。 清除空Region。

  1. 拷贝存活对象(Evacuation)
    Evacuation阶段是全暂停的。它负责把一部分region里的活对象拷贝到空region里去(并行拷贝),然后回收原本的region的空间。Evacuation阶段可以自由选择任意多个region来独立收集构成收集集合(collection set,简称CSet),CSet集合中Region的选定依赖于上文中提到的停顿预测模型,该阶段并不evacuate所有有活对象的region,只选择收益高的少量region来evacuate,这种暂停的开销就可以(在一定范围内)可控。
  • Full GC

G1的垃圾回收过程是和应用程序并发执行的,当Mixed GC的速度赶不上应用程序申请内存的速度的时候,Mixed G1就会降级到Full GC,使用的是Serial GC。Full GC会导致长时间的STW,应该要尽量避免。
导致G1 Full GC的原因可能有两个:

  1. Evacuation的时候没有足够的to-space来存放晋升的对象;
  2. 并发处理过程完成之前空间耗尽
    在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/767376.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Unity 角色控制器组件】

【Unity 角色控制器组件】 Character Controller: Unity 内置的一个组件,用于提供高级的物理控制,允许开发者控制角色的移动、跳跃和碰撞。 csharp csharp // 假设你已经有了一个带有Character Controller组件的游戏对象// 获取Character Co…

第十四章 路由器 OSPF 动态路由配置

实验目的 掌握 OSPF 协议的配置方法: 掌握查看通过动态路由协议 OSPF 学习产生的路由; 熟悉广域网线缆的链接方式; 实验背景 假设校园网通过一台三层交换机连到校园网出口路由器上, 路由器再和校园外的另一台路由器连接。…

Java高级重点知识点-19-Lambda

文章目录 Lambda表达式函数式编程思想Lambda表达式写法代码讲解 Lambda表达式 函数式编程思想 强调做什么,而不是以什么形式做。 以函数式接口Runnable为例讲解: public class LambdaDemo {public static void main(String[] args) {Runnable runnab…

relation-graph——数据组装+鼠标移入后的详情(自定义插槽的用法)——js技能提升

最近在写后台管理系统的时候,遇到一个需求,就是给我一些节点,让我渲染到页面上,效果图如下: 之前写过一篇文章关于relation-graph关系图组件http://t.csdnimg.cn/7BGYm的用法 还有一篇关于relation-graph——实现右击…

Python 编程快速上手——让繁琐工作自动化(第2版)读书笔记01 Python基础快速过关

Python 编程快速上手——让繁琐工作自动化(第2版)读书笔记01 Python基础快速过关 1 python基础概念 Python提供了高效的高级数据结构,还能简单有效地面向对象编程。 python运算符顺序 **——%——//——/——*——-——python中常见的数据…

【085】基于SpringBoot实现的网上音乐商城平台

系统介绍 视频演示 点击查看演示视频 基于SpringBoot实现的网上音乐商城平台分为管理员、用户两个角色,系统实现了用户注册和登陆、用户信息管理、用户加购、下单商品、购物车管理、订单管理、音乐分类、音乐商品管理、退出系统等功能 技术选型 开发工具&#…

大数据基础知识【大数据导论】

各位大佬好 ,这里是阿川的博客,祝您变得更强 个人主页:在线OJ的阿川 大佬的支持和鼓励,将是我成长路上最大的动力 阿川水平有限,如有错误,欢迎大佬指正 大数据基础知识前 必看 【大数据导论】—大数据序言…

旅游管理系统16021

摘 要 本文旨在设计和实现一个基于Spring Boot框架的旅游管理系统。该系统通过利用Spring Boot的快速开发特性和丰富的生态系统,提供了一个高效、可靠和灵活的解决方案。系统将实现旅游景点信息的管理、线路规划、跟团游玩、旅游攻略、酒店信息管理、订单管理和用户…

【C语言】inline 关键字

在C语言中,inline关键字用于建议编译器对函数进行内联展开,而不是像普通函数一样调用。内联函数的目的是减少函数调用的开销,特别是对于简单的、频繁调用的函数。 内联函数的定义和使用 定义内联函数 要定义一个内联函数,需要在…

PyTorch之nn.Module、nn.Sequential、nn.ModuleList使用详解

文章目录 1. nn.Module1.1 基本使用1.2 常用函数1.2.1 核心函数1.2.2 查看函数1.2.3 设置函数1.2.4 注册函数1.2.5 转换函数1.2.6 加载函数 2. nn.Sequential()2.1 基本定义2.2 Sequential类不同的实现2.3 nn.Sequential()的本质作用 3. nn.ModuleList参考资料 本篇文章主要介绍…

应用密码学—(扩展)欧几里得、DES、RSA、SHA-1算法

1. 欧几里得算法 1.1 分析算法的实现原理 欧几里德(Euclid)算法,也既常说的“辗转相除法”,公式为gcd(m, n) { return gcd(n, m%n); },对于任意两个正整数m、n,每次求的一个数字r m % n,然后把…

sideloadly 苹果自签和sidestore手机续签ipa记录

sideloadly 地址:https://sideloadly.io/#download 直接安装对应系统软件,然后吧ipa 拖到里面续签,缺点每7天需要电脑续签 如果续签保留数据需要对应的位置开启 enable file sharing 勾选 和 bundle id 修改 注意的地方需要电脑和手机appi…

无人机热成像分析图谱原理

一、热成像原理 热成像,也称为红外热成像或红外成像,是一种利用红外辐射(通常指的是热辐射)来获取物体表面温度分布信息的成像技术。在无人机上集成热成像传感器,可以远程捕获并分析目标物体的热特征,不受…

卸载node,下载nvm,下载node过程步骤及错误记录

网上有很多步骤,先跟着网上的步骤来: 卸载node和下载nvm步骤: window下安装并使用nvm(含卸载node、卸载nvm、全局安装npm)-CSDN博客 使用NVM下载和安装NodeJS教程-CSDN博客 出现的问题: 1.nvm配置sett…

ENVI5.6使用笔记

目录 1. ENVI安装扩展2. ENVI绘制高光谱3D数据立体图3. 对本次工作存档,下次打开软件可直接续档 1. ENVI安装扩展 从ENVI App Store下载商店envi_app_store.zip,解压得到ENVI_App_Store.sav,将其复制到ENVI的扩展文件夹下(例如E:…

中国桥梁空间分布数据

2020年中国桥梁空间分布数据,共包含102000余条数据。 数据属性表包括:地级市名、区县名、桥梁名称和经纬度。有shp和EXCEl两种格式数据。目前暂没有广西、广东和台湾三个省份数据。

【js】数组元素拼接、数组元素类型转换

一、数组元素拼接 二、数组元素类型转换 1、字符串数组 转换成 数字型数组 [1, 2, 3].map(Number) // [1,2,3] 2、数字型数组 转换成 字符串数组 [1, 2, 3].map(String) // [1, 2, 3]

干货:js解析url参数的作用、场景、方法和安全策略。

涉及到Web3D开发,Three.js和Babylon.js是两个备受推崇的引擎。它们都是基于WebGL的开源3D引擎,用于创建交互式的3D图形应用程序,但要细论起来,three.js普及度远超Babylon .js. 一、二者的介绍 Three.js: Three.js 是…

GitCode见证:华为云DevUI如何定义下一代前端开发

在当今快速发展的数字时代,前端开发已成为企业数字化转型的关键一环。随着用户对交互体验的期待不断增长,拥有一个强大、灵活且易于使用的前端解决方案变得至关重要。 DevUI的诞生,源于华为对研发工具的深入理解和长期积累,作为一…

【C++】开源:量化金融计算库QuantLib配置与使用

😏★,:.☆( ̄▽ ̄)/$:.★ 😏 这篇文章主要介绍量化交易库QuantLib配置与使用。 无专精则不能成,无涉猎则不能通。——梁启超 欢迎来到我的博客,一起学习,共同进步。 喜欢的朋友可以关注一下&#…