G1垃圾收集器(jdk9中将G1变成默认的垃圾收集器)

G1垃圾收集器(jdk9中将G1变成默认的垃圾收集器, 整体采用标记-整理算法,局部是通过是通过复制算法,不会产生内存碎片)

G1垃圾收集器是在jdk1.7中正式使用的全新的垃圾收集器以替代CMS。
G1的设计原则就是简化JVM性能调优,开发人员只需要简单的三步即可完成调优:

  1. 第一步,开启G1垃圾收集器
  2. 第二步,设置堆的最大内存
  3. 第三步,设置最大的停顿时间
    G1中提供了三种模式垃圾回收模式,Young GC、Mixed GC 和 Full GC,在不同的条件下被触发。

原理:
G1垃圾收集器相对比其他收集器而言,最大的区别在于它取消了年轻代、老年代的物理划分,取而代之的是将堆
划分为若干个区域(Region),这些区域中包含了有逻辑上的年轻代、老年代区域。
这样做的好处就是,我们再也不用单独的空间对每个代进行设置了,不用担心每个代内存是否足够。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5kEihlMU-1589262967722)(C:\Users\VIolet\AppData\Roaming\Typora\typora-user-images\image-20200512121536632.png)]

在G1划分的区域中,年轻代的垃圾收集依然采用暂停所有应用线程的方式,将存活对象拷贝到老年代或者Survivor
空间,G1收集器通过将对象从一个区域复制到另外一个区域,完成了清理工作。
这就意味着,在正常的处理过程中,G1完成了堆的压缩(至少是部分堆的压缩),这样也就不会有cms内存碎片问题的存在了。

在G1中,有一种特殊的区域,叫Humongous区域。
如果一个对象占用的空间超过了分区容量50%以上,G1收集器就认为这是一个巨型对象
这些巨型对象,默认直接会被分配在老年代,但是如果它是一个短期存在的巨型对象,就会对垃圾收集器造
成负面影响。
为了解决这个问题,G1划分了一个Humongous区,它用来专门存放巨型对象。如果一个H区装不下一个巨型
对象,那么G1会寻找连续的H分区来存储。为了能找到连续的H区,有时候不得不启动Full GC

G1的Young GC工作原理
Young GC主要是对Eden区进行GC,它在Eden空间耗尽时会被触发。
Eden空间的数据移动到Survivor空间中,如果Survivor空间不够,Eden空间的部分数据会直接晋升到年老代
空间。Survivor区的数据移动到新的Survivor区中,也有部分数据晋升到老年代空间中。
最终Eden空间的数据为空,GC停止工作,应用线程继续执行。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LNPSy9ri-1589262967725)(C:\Users\VIolet\AppData\Roaming\Typora\typora-user-images\image-20200512134650538.png)]

Remembered Set(已记忆集合)

在GC年轻代的对象时,我们如何找到年轻代中对象的根对象呢?
根对象可能是在年轻代中,也可以在老年代中,那么老年代中的所有对象都是根么?
如果全量扫描老年代,那么这样扫描下来会耗费大量的时间。
于是,G1引进了RSet的概念。它的全称是Remembered Set,其作用是跟踪指向某个堆内的对象引用。每个Region初始化时,会初始化一个RSet,该集合用来记录并跟踪其它Region指向该Region中对象的引用,每个
Region默认按照512Kb划分成多个Card,所以RSet需要记录的东西应该是 xx Region的 xx Card。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8DXRktpd-1589262967726)(C:\Users\VIolet\AppData\Roaming\Typora\typora-user-images\image-20200512134741497.png)]

Mixed GC

当越来越多的对象晋升到老年代old region时,为了避免堆内存被耗尽,虚拟机会触发一个混合的垃圾收集器,即
Mixed GC,该算法并不是一个Old GC,除了回收整个Young Region,还会回收一部分的Old Region,这里需要注
意:是一部分老年代,而不是全部老年代,可以选择哪些old region进行收集,从而可以对垃圾回收的耗时时间进
行控制。也要注意的是Mixed GC 并不是 Full GC。
MixedGC什么时候触发? 由参数 -XX:InitiatingHeapOccupancyPercent=n 决定。默认:45%,该参数的意思是:
当老年代大小占整个堆大小百分比达到该阀值时触发。
它的GC步骤分2步:

  1. 全局并发标记(global concurrent marking)
  2. 拷贝存活对象(evacuation)

全局并发标记
全局并发标记,执行过程分为五个步骤:
初始标记(initial mark,STW)
标记从根节点直接可达的对象,这个阶段会执行一次年轻代GC,会产生全局停顿。
根区域扫描(root region scan)
G1 GC 在初始标记的存活区扫描对老年代的引用,并标记被引用的对象。
该阶段与应用程序(非 STW)同时运行,并且只有完成该阶段后,才能开始下一次 STW 年轻代垃圾回
收。
并发标记(Concurrent Marking)
G1 GC 在整个堆中查找可访问的(存活的)对象。该阶段与应用程序同时运行,可以被 STW 年轻代垃
圾回收中断。
重新标记(Remark,STW)
该阶段是 STW 回收,因为程序在运行,针对上一次的标记进行修正。
清除垃圾(Cleanup,STW)
清点和重置标记状态,该阶段会STW,这个阶段并不会实际上去做垃圾的收集,等待evacuation阶段来
回收。

拷贝存活对象
Evacuation阶段是全暂停的。该阶段把一部分Region里的活对象拷贝到另一部分Region中,从而实现垃圾的回收
清理。

G1收集器相关参数

-XX:+UseG1GC
使用 G1 垃圾收集器
-XX:MaxGCPauseMillis
设置期望达到的最大GC停顿时间指标(JVM会尽力实现,但不保证达到),默认值是 200 毫秒。
-XX:G1HeapRegionSize=n
设置的 G1 区域的大小。值是 2 的幂,范围是 1 MB 到 32 MB 之间。目标是根据最小的 Java 堆大小划
分出约 2048 个区域。
默认是堆内存的1/2000。
-XX:ParallelGCThreads=n
设置 STW 工作线程数的值。将 n 的值设置为逻辑处理器的数量。n 的值与逻辑处理器的数量相同,最多
为 8。
-XX:ConcGCThreads=n
设置并行标记的线程数。将 n 设置为并行垃圾回收线程数 (ParallelGCThreads) 的 1/4 左右。
-XX:InitiatingHeapOccupancyPercent=n
设置触发标记周期的 Java 堆占用率阈值。默认占用率是整个 Java 堆的 45%。
-XX:+UseG1GC -XX:MaxGCPauseMillis=100 -XX:+PrintGCDetails -Xmx256m
#日志
[GC pause (G1 Evacuation Pause) (young), 0.0044882 secs]
 [Parallel Time: 3.7 ms, GC Workers: 3]
  [GC Worker Start (ms): Min: 14763.7, Avg: 14763.8, Max: 14763.8, Diff: 0.1]
   #扫描根节点
  [Ext Root Scanning (ms): Min: 0.2, Avg: 0.3, Max: 0.3, Diff: 0.1, Sum: 0.8]
   #更新RS区域所消耗的时间
  [Update RS (ms): Min: 1.8, Avg: 1.9, Max: 1.9, Diff: 0.2, Sum: 5.6]
    [Processed Buffers: Min: 1, Avg: 1.7, Max: 3, Diff: 2, Sum: 5]
  [Scan RS (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]
  [Code Root Scanning (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]
   #对象拷贝
  [Object Copy (ms): Min: 1.1, Avg: 1.2, Max: 1.3, Diff: 0.2, Sum: 3.6]
  [Termination (ms): Min: 0.0, Avg: 0.1, Max: 0.2, Diff: 0.2, Sum: 0.2]
    [Termination Attempts: Min: 1, Avg: 1.0, Max: 1, Diff: 0, Sum: 3]
  [GC Worker Other (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]
  [GC Worker Total (ms): Min: 3.4, Avg: 3.4, Max: 3.5, Diff: 0.1, Sum: 10.3]
  [GC Worker End (ms): Min: 14767.2, Avg: 14767.2, Max: 14767.3, Diff: 0.1]
 [Code Root Fixup: 0.0 ms]
 [Code Root Purge: 0.0 ms]
 [Clear CT: 0.0 ms] #清空CardTable
 [Other: 0.7 ms]
  [Choose CSet: 0.0 ms] #选取CSet
  [Ref Proc: 0.5 ms] #弱引用、软引用的处理耗时
  [Ref Enq: 0.0 ms] #弱引用、软引用的入队耗时
  [Redirty Cards: 0.0 ms]
  [Humongous Register: 0.0 ms] #大对象区域注册耗时
  [Humongous Reclaim: 0.0 ms] #大对象区域回收耗时
  [Free CSet: 0.0 ms]
 [Eden: 7168.0K(7168.0K)->0.0B(13.0M) Survivors: 2048.0K->2048.0K Heap:
55.5M(192.0M)->48.5M(192.0M)] #年轻代的大小统计
[Times: user=0.00 sys=0.00, real=0.00 secs]

对于G1垃圾收集器优化建议
年轻代大小
避免使用 -Xmn 选项或 -XX:NewRatio 等其他相关选项显式设置年轻代大小。
固定年轻代的大小会覆盖暂停时间目标。
暂停时间目标不要太过严苛
G1 GC 的吞吐量目标是 90% 的应用程序时间和 10%的垃圾回收时间。
评估 G1 GC 的吞吐量时,暂停时间目标不要太严苛。目标太过严苛表示您愿意承受更多的垃圾回收开
o 等其他相关选项显式设置年轻代大小。
固定年轻代的大小会覆盖暂停时间目标。
暂停时间目标不要太过严苛
G1 GC 的吞吐量目标是 90% 的应用程序时间和 10%的垃圾回收时间。
评估 G1 GC 的吞吐量时,暂停时间目标不要太严苛。目标太过严苛表示您愿意承受更多的垃圾回收开
销,而这会直接影响到吞吐量。

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值