JVM学习——G1垃圾回收器的工作原理

ParNew和CMS垃圾回收器的痛点

Stop the World现象会对系统的运行是有一定的影响。所以对垃圾回收器的优化,都是朝着减少“Stop the World”的目标去做。

G1垃圾回收器

G1垃圾回收器是可以同时回收新生代和老年代的对象的,不需要两个垃圾回收器配合起来运作。

特点1:就是把java堆内存拆分为多个大小相等的Region。

G1也会有新生代和老年代的概念,但是只是逻辑上的概念。

特点2:可以让我们设置一个垃圾回收的预期停顿时间

也就是说我们可以指定:希望G1在垃圾回收的时候,可以保证在1小时内由G1垃圾回收导致的“Stop the World”也就是系统停顿的时间,不能超过1分钟。

G1是如何做到对垃圾回收导致的系统停顿可控的?

其实G1如果要做到这一点,他就必须要追踪每个Region里的回收价值

回收价值:必须清楚每个Region里的对象有多少是垃圾,如果对这个Region进行垃圾回收,需要耗费多长时间,可以回收掉多少垃圾。

总结:G1可以做到让你来设定垃圾回收对系统的影响,他自己通过把内存拆分为大量小Region,以及追踪每个Region中可以回收的对象大小和预估时间,最后在垃圾回收的时候,尽量把垃圾回收对系统造成的影响控制在你指定的时间范围内,同时在有限的时间内尽量回收尽可能多的垃圾对象。

Region可能属于新生代也可能是老年代

刚开始Region可能谁都不属于,然后分配给了新生代,放了很多新生代的内存,然后触发了垃圾回收这个Region,然后下一次同一个Region可能又被分配了老年代了。所有在G1里面Region随时属于新生代也会属于老年代,因此也没有所谓的新生代和老年代一说。

实际上新生代和老年代各自的内存区域是不停的变动的,由G1自动控制。

根据设定的预期系统停顿时间,来选择最少回收时间和最多回收对象的Region进行垃圾回收,保证垃圾回收对系统停顿的影响在可控范围内,同时还能尽可能回收更多的对象。

问题1:G1是如何工作的?

问题2:对象什么时候进入新生代的Region?

问题3:什么时候触发Region GC?

问题4:什么时候对象进入老年代的Region?

问题5:什么时候触发老年代的Region GC?

如何设定G1对应的内存大小

G1对应的是一大堆的Region内存区域,每个Region的大小是一致的。

问题来了:到底有多少个Region?每个Region的大小是多大?

其实这个默认情况下自动计算和设置的,我们可以给整个堆内存设置一个大小,比如说用

”-Xms“和”-Xmx“来设置堆内存的大小。

然后jvm启动的时候一旦发现你使用的是G1垃圾回收器,可以使用”-XX:+UseG1GC“来指定使用G1垃圾回收器,此时会自动用堆大小除以2048.

因为jvm最大可以有2048个Region,然后Region的大小必须是2的倍数,比如1MB,2MB,4MB之类的,

比如说堆内存是4G,那么就是4096MB,此时除以2048个Region,每个Region的大小就是2MB,

大概就是这样子来决定Region的数量和大小的,大家一般保持默认的计算方式就可以了。

手动方式来指定,则是”-XX:G1HeapRegionSize“,

刚开始的时候,默认新生代对堆内存的占比是5%,也就是占据200MB左右的内存,对应大概100个Region,这个是可以通过”-XX:G1NewSizePercent“ 来设置新生代初始占比的,其实维持这个默认值即可。

因为在系统运行中,JVM其实会不停的给新生代增加更多的Region,但是最多新生代的占比不会超过60%,可以通过”-XX:G1MaxNewSizePercent“

而且一旦Region进行了垃圾回收,此时新生代的Region数量还会减少,这些其实都是动态的。

新生代还有Eden和Survivor的概念吗?

G1虽然把内存划分为很多的Region,但是其实还是有新生代,老年代的区分

而且新生代里还是有Eden和Survivor的划分的,比如新生代开始初始化的时候有100个Region,那么有可能80个Region是Eden,两个survivor各占10个Region。

随着对象不停的在新生代里分配,属于新生代的Region会不断增加,Eden和survivor对应的Region也会不断的增加。

G1的新生代垃圾回收

G1的新生代有Eden和Survivor的区分,触发垃圾回收的机制也是类似的。

随著不停的在新生代的Eden对应的Region中放对象,JVM就会不停的给新生代加入更多的Region,直至新生代占据堆大小的最大比例60%。

一旦新生代达到了设定的占据堆内存的最大大小60%,比如有120个Region,里面Eden占了100个Region,每个Survivor是10个Region,而且Eden区占满了对象,这个时候就会触发新生代的GC,G1就会用复制算法进行垃圾回收,进入”Stop the World“状态,然后把Eden对应的Region中的存活对象放入S1对应的Region中,接着回收掉Eden对应的Region中的垃圾对象。

但是G1是可以设置目标GC停顿时间的,也就是G1执行GC的时候最多可以让系统停顿多长时间,可以通过”-XX:MacGCPauseMills“参数来设定,默认值是200ms。

G1堆每个Region追踪回收需要多少时间,可以回收多少对象来选择回收一部分的Region保证GC停顿时间控制在指定范围内,尽可能多的回收掉一些对象。

对象什么时候进入老年代?

G1的内存模型下,新生代和老年代各自都会占据一定的Region,老年代也会有自己的Region。

按照新生代最多占据堆内存60%的Region来算,老年代最多可以占40%的Region。

满足下面条件就会进入老年代中:

1、对象在新生代躲过很多次的垃圾回收,达到一定的年龄。”-XX:MaxTenuringThreshold“ 参数可以设置这个年龄。

2、动态年龄判定规则,如果一旦发现某次新生代GC过后,存活对象超过了Survivor的50%,此时就会判断一下,比如年龄1、2、3、4岁的对象大小超过了Survivor的50%,此时4岁以上的对象全都进入老年代,这就是动态年龄判定规则。

大对象Region

G1提供了专门的Region来存放大对象,而不是让大对象进入老年代的Region中。

大对象的判定:就是一个对象超过Region大小的50%,就会被放入大对象专门的Region中

如果大对象太大,就会横跨多个Region来存放。

大对象Region不属于新生代和老年代,但是在新生代和老年底垃圾回收的时候,会顺带大对象Region一起回收

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值