当前位置: 首页 > news >正文

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. 并发处理过程完成之前空间耗尽
    在这里插入图片描述

相关文章:

G1 垃圾收集器

从 JDK1.9 开始默认 G1,应用在多处理器和大容量内存环境中。 基础概念 Region G1 给整一块Heap内存区域均匀等分了N个 Region,N 默认情况下是 2048。 Region的大小只能是1M、2M、4M、8M、16M或32M (1-32M,并且为2的指数),比如-Xmx16g -Xms…...

Linux Ubuntu 20.04.06 安装Onboard虚拟键盘教程

目录 一、在线安装 二、源码安装 三、包安装 四、设置 五、禁用系统键盘 一、在线安装 sudo apt-get update #更新软件源 sudo apt-get install onboard #安装Onboard sudo apt-get purge onboard # 卸载 安装后,如果在终端使用命令:onboard 启…...

简介空间复杂度

我们承接上一篇博客。我们写了时间复杂度之后,我们就要来介绍一下另一个相关复杂度了。空间复杂度。我觉得大家应该对空间复杂度认识可能比较少一些。我就是这样,我很少看见题目中有明确要求过空间复杂度的。但确实有这个是我们不可忽视的,所…...

windows server2016搭建AD域服务器

文章目录 一、背景二、搭建AD域服务器步骤三、生成可供java程序使用的keystore文件四、导出某用户的keytab文件五、主机配置hosts文件六、主机确认是否能ping通本人其他相关文章链接 一、背景 亲测可用,之前搜索了很多博客,啥样的都有,就是不介绍报错以…...

android deep links即scheme uri跳转以及googlePlay跳转配置

对于googlePlay的Custom URL就是googlePlay上APP网址: https://play.google.com/store/apps/details?idcom.yourapp如果是国内一些应用,则考虑market://包名等方式,自行百度。 对于Android URI Scheme: 首先需要在Manifest xm…...

QT5.14.2与Mysql8.0.16配置笔记

1、前言 我的QT版本为 qt-opensource-windows-x86-5.14.2。这是QT官方能提供的自带安装包的最近版本,更新的版本需要自己编译源代码,可点击此链接进行下载:Index of /archive/qt/5.14/5.14.2,选择下载 qt-opensource-windows-x86…...

判断是否为完全二叉树

目录 分析 分析 1.完全二叉树的概念:对于深度为K的,有n个结点的二叉树,当且仅当其每一个结点都与深度为K的满二叉树中编号从1至n的结点一一对应时称之为完全二叉树。 要注意的是满二叉树是一种特殊的完全二叉树。 2.思路:可以采…...

【笔记】记一次redis将从节点变成主节点 主节点变成从节点

1.连上虚拟机centos7 2.打开finalshell连接虚拟机 将从节点变为主节点 输出redis-cli -p 要变成主节点的从节点 -a此从节点的密码 输入 replicaof no one 查看端口状态 info replication 总结: redis-cli -p 端口号 -a 密码 replicaof no one info replicati…...

解析Java中1000个常用类:DoubleSummaryStatistics类,你学会了吗?

在线工具站 推荐一个程序员在线工具站:程序员常用工具(http://cxytools.com),有时间戳、JSON格式化、文本对比、HASH生成、UUID生成等常用工具,效率加倍嘎嘎好用。程序员资料站 推荐一个程序员编程资料站:程序员的成长之路(http://cxyroad.com),收录了一些列的技术教程…...

WAIC热点聚焦|新质生产力与低空经济

WAIC热点聚焦|新质生产力与低空经济 概览 # WAIC热点聚焦 | 新质生产力与低空经济## 1. 新质生产力定义与特点 - 新质生产力是在新的经济社会发展阶段中形成的,具有变革性和高增长潜力的生产能力。## 2. 低空经济概念与构成 ### 2.1 低空经济定义 - 低空经济是依托…...

Docker部署ETCD 3.5.14(保姆级图文教程)

系列文章目录 Docker部署Nginx 1.21.5(保姆级图文教程) Docker部署MySQL 8.3.0(保姆级图文教程) Docker部署ETCD 3.5.14(保姆级图文教程) 文章目录 一、环境二、拉取镜像2.1 查找 Docker Hub 上的 ETCD 镜像…...

2024年7月6日 (周六) 叶子游戏新闻

自动电脑内部录音器AutoAudioRecorder: 是一款免费的自动音频录制软件,可直接将电脑内部所有的声音录制成 mp3/wav 文件,包括音乐、游戏直播、网络会议、聊天通话等音频源。 卸载工具 HiBitUninstaller: Windows上的软件卸载工具 《不羁联盟》制作人&…...

python爬虫入门(二)之Requests库

一、储备篇 1、requests库让我们可以通过python代码去构建和发送HTTP请求 2、第三方库,要先安装 python终端,输入pip install requests successfully installed:安装成功 requirement already satisfied: 说明已经安装过,无需…...

Git 操作补充:cherry-pick、变基

1. 挑选提交合并 git cherry-pick 对于多分支的代码库,将代码从一个分支转移到另一个分支是一种常见的需求,这可以分成两种情况:一种情况是,你需要另一个分支的所有代码变动,那么就采用 git merge;另一种情…...

在 PostgreSQL 中,如何处理大规模的文本数据以提高查询性能?

文章目录 一、引言二、理解 PostgreSQL 中的文本数据类型三、数据建模策略四、索引选择与优化五、查询优化技巧六、示例场景与性能对比七、分区表八、数据压缩九、定期维护十、总结 在 PostgreSQL 中处理大规模文本数据以提高查询性能 一、引言 在当今的数据驱动的世界中&…...

秋招提前批面试经验分享(下)

⭐️感谢点开文章👋,欢迎来到我的微信公众号!我是恒心😊 一位热爱技术分享的博主。如果觉得本文能帮到您,劳烦点个赞、在看支持一下哈👍! ⭐️我叫恒心,一名喜欢书写博客的研究生在读…...

零基础STM32单片机编程入门(七)定时器PWM波输出实战含源码视频

文章目录 一.概要二.PWM产生框架图三.CubeMX配置一个TIME输出1KHZ,占空比50%PWM波例程1.硬件准备2.创建工程3.测量波形结果 四.CubeMX工程源代码下载五.讲解视频链接地址六.小结 一.概要 脉冲宽度调制(PWM),是英文“Pulse Width Modulation”的缩写&…...

【ubuntu自启shell脚本】——在ubuntu中如何使用系统自带的启动应用程序设置开机自启自己的本地shell脚本

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、设置开机自启shell脚本1.使用 gnome-session-properties2.测试的shell例程代码 总结 前言 在Ubuntu系统中设置开机自启脚本是一种重要的自动化方法。开机自…...

nodejs配置国内镜像

# 设置淘宝镜像 npm config set registry https://registry.npmmirror.com# 查看镜像源 npm get registry...

【JavaEE】多线程进阶

🤡🤡🤡个人主页🤡🤡🤡 🤡🤡🤡JavaEE专栏🤡🤡🤡 文章目录 1.锁策略1.1悲观锁和乐观锁1.2重量级锁和轻量级锁1.3自旋锁和挂起等待锁1.4可…...

大话软工笔记—需求分析概述

需求分析,就是要对需求调研收集到的资料信息逐个地进行拆分、研究,从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要,后续设计的依据主要来自于需求分析的成果,包括: 项目的目的…...

Debian系统简介

目录 Debian系统介绍 Debian版本介绍 Debian软件源介绍 软件包管理工具dpkg dpkg核心指令详解 安装软件包 卸载软件包 查询软件包状态 验证软件包完整性 手动处理依赖关系 dpkg vs apt Debian系统介绍 Debian 和 Ubuntu 都是基于 Debian内核 的 Linux 发行版&#xff…...

LLM基础1_语言模型如何处理文本

基于GitHub项目:https://github.com/datawhalechina/llms-from-scratch-cn 工具介绍 tiktoken:OpenAI开发的专业"分词器" torch:Facebook开发的强力计算引擎,相当于超级计算器 理解词嵌入:给词语画"…...

【JavaSE】绘图与事件入门学习笔记

-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角,以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向,距离坐标原点x个像素;第二个是y坐标,表示当前位置为垂直方向,距离坐标原点y个像素。 坐标体系-像素 …...

VM虚拟机网络配置(ubuntu24桥接模式):配置静态IP

编辑-虚拟网络编辑器-更改设置 选择桥接模式,然后找到相应的网卡(可以查看自己本机的网络连接) windows连接的网络点击查看属性 编辑虚拟机设置更改网络配置,选择刚才配置的桥接模式 静态ip设置: 我用的ubuntu24桌…...

安全突围:重塑内生安全体系:齐向东在2025年BCS大会的演讲

文章目录 前言第一部分:体系力量是突围之钥第一重困境是体系思想落地不畅。第二重困境是大小体系融合瓶颈。第三重困境是“小体系”运营梗阻。 第二部分:体系矛盾是突围之障一是数据孤岛的障碍。二是投入不足的障碍。三是新旧兼容难的障碍。 第三部分&am…...

Java详解LeetCode 热题 100(26):LeetCode 142. 环形链表 II(Linked List Cycle II)详解

文章目录 1. 题目描述1.1 链表节点定义 2. 理解题目2.1 问题可视化2.2 核心挑战 3. 解法一:HashSet 标记访问法3.1 算法思路3.2 Java代码实现3.3 详细执行过程演示3.4 执行结果示例3.5 复杂度分析3.6 优缺点分析 4. 解法二:Floyd 快慢指针法(…...

Java并发编程实战 Day 11:并发设计模式

【Java并发编程实战 Day 11】并发设计模式 开篇 这是"Java并发编程实战"系列的第11天,今天我们聚焦于并发设计模式。并发设计模式是解决多线程环境下常见问题的经典解决方案,它们不仅提供了优雅的设计思路,还能显著提升系统的性能…...

leetcode_69.x的平方根

题目如下 &#xff1a; 看到题 &#xff0c;我们最原始的想法就是暴力解决: for(long long i 0;i<INT_MAX;i){if(i*ix){return i;}else if((i*i>x)&&((i-1)*(i-1)<x)){return i-1;}}我们直接开始遍历&#xff0c;我们是整数的平方根&#xff0c;所以我们分两…...

深度解析云存储:概念、架构与应用实践

在数据爆炸式增长的时代&#xff0c;传统本地存储因容量限制、管理复杂等问题&#xff0c;已难以满足企业和个人的需求。云存储凭借灵活扩展、便捷访问等特性&#xff0c;成为数据存储领域的主流解决方案。从个人照片备份到企业核心数据管理&#xff0c;云存储正重塑数据存储与…...