JVM虚拟机--Garbage FIrst收集器

JVM虚拟机–Garbage FIrst收集器

JDK9 发布时确认其为服务器端默认的垃圾收集器

与旧垃圾收集器理念差异

过去的垃圾收集器都是有确定的目标范围,要么是在新生代(Mior GC),要么老年代(Major GC),或者整个Java堆(Full GC)

G1可以面向堆内存任何部分来组成回收集,衡量标准不是基于分代,而是那块内存中垃圾数量,Mixed GC模式

设计目标是 在用户线程停顿时间可控的情况下 尽量获得更高的吞吐量

Region

将连续的堆划分为多个大小相等的独立区域,每一个区域都可以根据需要扮演新生代空间的Eden或者Survivor空间

Humongous区域,Region内部专门用来存储大对象的空间,超过Region一半大小即可认为为大对象

每个Region大小通过参数-XX:G1HeapRegionSize来设计 取值范围为1MB-32MB 且应为2的N次幂。

对于超过Region大小的超级大对象 会被存放在N个连续Humongous Region区域 G1的大多数行为都见其作为老年代的一部分来看待

G1保留了新生代和老年代的概念,但是不再是固定的,是一系列区域的动态集合,不需要在连续。

每次回收都是以Region作为最小单元,每次收集区域都是Region的整数倍大小

具体实现

1:初始标记。标记GC Roots直接关联的对象,修改TAMS指针,此阶段用户线程停顿
2:并发标记。与用户线程并发执行,从GC Roots开始进行跟可达分析 标记垃圾对象
3:最终标记。根据SATB记录对并发标记阶段被错误标记的对象重新扫描
4:筛选回收。更新Region的统计数据,根据回收价值排序,根据用户期望的回收停顿时间,选择任意多个Region组成回收集,对存活对象移动到空的Region,然后整个Region回收,所以G1采用的是标记-复制算法,不会产生内存碎片问题。

TAMS指针:在并发标记阶段用户线程产生新的对象需要分配内存空间,所以Region通过两个指针,从Region内存空间划分出一块用来分配新对象,同样如果空间不足以容纳对象,也会导致用户线程被迫终止执行,出发Full GC

SATB:原始快照算法,即在并发标记阶段出现某个灰色节点到白色节点的引用被删除,从而出现对象被错误标记为垃圾,G1通过记录下这些删除的引用,在最终标记过程重新进心扫描。

G1收集器会跟踪每个Region的价值,价值指的是回收此块Region所获得的内存空间以及回收所需时间的经验值,在后台维护一个优先级列表,每次根据用户设定的允许收集的停顿时间(-XX:MaxGCPauseMills,默认200毫秒),优先处理价值效益最大的Region

那么可不可以把MaxGCPauseMills设置的特别小呢?

还是要根据实际情况来分析,G1最后的回收阶段 终究是要将存活对象进行复制,是要消耗时间的,如果参数设置的过小,内存回收速度跟不上内存分配速度,最终还是会导致出发Full GC反而降低性能

如何解决跨Region引用?

在之前的垃圾回收器进行新生代回收时,会维护一个记忆集,记录了老年代区域中那些区域内有对象引用新生代对象,从而避免对整个老年代区域全扫描。

这里同样也是使用的记忆集,每个Region都会维护一个记忆集,具体的数据结构是一个哈希表,key是指向本Region的其他Region地址,vlaue是一个卡表的索引号集合,由于Region数量远大于其他收集器分代数量,所以G1内存占用负担更大,根据经验,至少要耗费10%到20%的堆内存来维持收集器工作。

从G1开始垃圾收集器的设计理念都是尽可能追求能用应付用户程序的内存分配速率,而不追求要将所有垃圾全部清理掉。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值