Garbage First收集器(简称G1)

简介: 本文详细介绍了G1垃圾收集器的设计理念、基于Region的内存布局、大对象处理、记忆集的复杂应用、并发标记阶段的挑战以及可靠的停顿预测模型。

概述:Garbage First(简称G1)收集器是垃圾收集器技术发展历史上的里程碑式的成果,它开创了收集器面向局部收集的设计思路和基于Region的内存布局形式。

G1开创的基于Region的堆内存布局是它能够实现这个目标的关键。虽然G1也仍是遵循分代收集理 论设计的,但其堆内存的布局与其他收集器有非常明显的差异:G1不再坚持固定大小以及固定数量的 分代区域划分,而是把连续的Java堆划分为多个大小相等的独立区域(Region),每一个Region都可以 根据需要,扮演新生代的Eden空间、Survivor空间,或者老年代空间。收集器能够对扮演不同角色的 Region采用不同的策略去处理,这样无论是新创建的对象还是已经存活了一段时间、熬过多次收集的 旧对象都能获取很好的收集效果。

Region中还有一类特殊的Humongous区域,专门用来存储大对象。G1认为只要大小超过了一个 Region容量一半的对象即可判定为大对象。每个Region的大小可以通过参数-XX:G1HeapRegionSize设 定,取值范围为1MB~32MB,且应为2的N次幂。而对于那些超过了整个Region容量的超级大对象, 将会被存放在N个连续的Humongous Region之中,G1的大多数行为都把Humongous Region作为老年代 的一部分来进行看待。

当然,它的实现也很复杂。

譬如,将Java堆分成多个独立Region后,Region里面存在的跨Region引用对象如何解决?

解决的思路我们已经知道:使用记忆集避免全堆作为GC Roots扫描,但在G1收集器上记忆集的应用其实要复杂很多,它的每个Region都维护有自己的记忆集,这些记忆集会记录下别的Region 指向自己的指针,并标记这些指针分别在哪些卡页的范围之内。G1的记忆集在存储结构的本质上是一 种哈希表,Key是别的Region的起始地址,Value是一个集合,里面存储的元素是卡表的索引号。这 种“双向”的卡表结构(卡表是“我指向谁”,这种结构还记录了“谁指向我”)比原来的卡表实现起来更 复杂,同时由于Region数量比传统收集器的分代数量明显要多得多,因此G1收集器要比其他的传统垃 圾收集器有着更高的内存占用负担。

譬如,在并发标记阶段如何保证收集线程与用户线程互不干扰地运行?

这里首先要解决的是用户线程改变对象引用关系时,必须保证其不能打破原本的对象图结构,导致标记结果出现错误。CMS收集器采用增量更新算法实现,而G1 收集器则是通过原始快照(SATB)算法来实现的。此外,垃圾收集对用户线程的影响还体现在回收过 程中新创建对象的内存分配上,程序要继续运行就肯定会持续有新对象被创建,G1为每一个Region设 计了两个名为TAMS(Top at Mark Start)的指针,把Region中的一部分空间划分出来用于并发回收过 程中的新对象分配,并发回收时新分配的对象地址都必须要在这两个指针位置以上。

譬如,怎样建立起可靠的停顿预测模型?

用户通过-XX:MaxGCPauseMillis参数指定的停顿时间 只意味着垃圾收集发生之前的期望值,但G1收集器要怎么做才能满足用户的期望呢?G1收集器的停顿 预测模型是以衰减均值(Decaying Average)为理论基础来实现的,在垃圾收集过程中,G1收集器会记 录每个Region的回收耗时、每个Region记忆集里的脏卡数量等各个可测量的步骤花费的成本,并分析得 出平均值、标准偏差、置信度等统计信息。这里强调的“衰减平均值”是指它会比普通的平均值更容易 受到新数据的影响,平均值代表整体平均状态,但衰减平均值更准确地代表“最近的”平均状态。换句 话说,Region的统计状态越新越能决定其回收的价值。然后通过这些信息预测现在开始回收的话,由 哪些Region组成回收集才可以在不超过期望停顿时间的约束下获得最高的收益。

目录
相关文章
|
9月前
|
数据采集 自然语言处理 API
集运物流企业构建反向海淘系统的完整投入分析,涵盖技术、物流、合规、运营四大核心模块的详细成本与资源
集运物流企业构建反向海淘系统需投入技术、物流、合规、运营四大模块资源。技术方面涵盖用户端与商家端开发、API对接及智能清关系统,首年成本约150万至800万人民币。物流基建包括国内集运仓、国际运输和海外派送,涉及浮动成本。合规投入涉及跨境资质、国际认证及数据安全。运营阶段注重市场推广、客服体系及品牌建设。总初期启动成本150万至800万,持续运营年成本100万至500万。成功要素包括差异化服务、技术护城河和本地化运营。
|
5月前
|
XML 人工智能 Java
注入Java Bean的方式
本文总结了 Spring Boot 中常见的 Bean 注入方式,包括字段注入(`@Autowired`)、构造器注入(推荐)、Setter 方法注入、`@Resource` 按名称注入、`@Bean` 定义复杂 Bean、`@Value` 注入配置值、XML 配置、`ApplicationContextAware` 手动获取 Bean 以及 JSR-330 的 `@Inject`。同时分析了 Setter 注入逐渐被淡化的原因,强调构造器注入的不可变性和安全性优势,并推荐结合 Lombok 简化代码。文章还提供了按需选择注解的建议和最佳实践,帮助开发者根据场景选择合适的依赖注入方式。
273 49
|
8月前
|
存储 算法 Java
G1原理—4.G1垃圾回收的过程之Young GC
本文详细解析了G1垃圾回收器中YGC(Young Generation Collection)的完整流程,包括并行与串行处理阶段。内容涵盖YGC相关参数设置、YGC与Mixed GC及FGC的关系、新生代垃圾回收的具体步骤(如标记存活对象、复制到Survivor区、动态调整Region数量等),以及并行阶段的多线程操作和串行阶段的关键任务(如处理软引用、整理卡表、重构RSet)。
G1原理—4.G1垃圾回收的过程之Young GC
|
存储 监控 Java
OpenFeign请求拦截器组件RequestInterceptor原理与使用场景
该文章讲述了OpenFeign中的请求拦截器组件RequestInterceptor的原理及其常见使用场景。
OpenFeign请求拦截器组件RequestInterceptor原理与使用场景
|
8月前
|
自然语言处理 算法 API
一文揭秘|如何速成RAG+Agent框架大模型应用搭建(一)
一文揭秘|如何速成RAG+Agent框架大模型应用搭建
475 0
|
Kubernetes 负载均衡 安全
ECI Pod概述
ECI能为Kubernetes提供基础的容器Pod运行环境
556 5
|
Java Spring 容器
Spring Boot 启动源码解析结合Spring Bean生命周期分析
Spring Boot 启动源码解析结合Spring Bean生命周期分析
415 11
|
存储 算法 自动驾驶
【论文速递】CVPR2022 - 用于语义分割的跨图像关系知识蒸馏
【论文速递】CVPR2022 - 用于语义分割的跨图像关系知识蒸馏
|
存储 缓存 Java
Java volatile关键字-单例模式的双重锁为什么要加volatile
Java volatile关键字--单例模式的双重锁为什么要加volatile
321 10
|
搜索推荐
新手如何发网站外链,网站的外链如何发,发外链的方法集合
一和大家分享一下我是如何做反连接链的。一般做反连接我只追求两件事情。一、数量。二、稳定性。对于像我这样的新人和缺乏资源的人来讲能做的就是增加外链数量,做好外链的稳定性工作。所谓的稳定性就是发了的外链就要尽量让它别消失,这点群发软件就很难做到,特别是英文站。
3993 0