一、G1垃圾回收器介绍
为了解决CMS算法产生空间碎片和其他一系列的问题缺陷,HotSpot虚拟机团队提出了另外一种垃圾回收策略,G1(Garbage First)算法。通过参数-XX:+UserG1GC来启用。这个算法在JDK7被正式推出。
G1垃圾回收算法主要应用在多CPU大内存的服务中,在满足高吞吐量的同事,尽可能的满足垃圾回收时的暂停时间,G1的设计应用场景:
- 垃圾收集线程和应用线程并发执行,和CMS一样。
- 空闲内存亚索时避免冗长的暂停时间
- 应用需要更多可预测的GC暂停时间
- 不希望牺牲太多的吞吐性能
- 不需要很大的java堆
1、堆内存结构:
1、以往的垃圾回收算法,比如CMS,堆内存结构如下:
年轻代/新生代:eden space+2个survivor
老年代:old space
持久代:1.8之前的perm space
元空间:1.8之后的metaspace(元空间)
上面这些space必须是地址连续的空间。
2、在G1算法中,采用了另一种完全不同的方式组织堆内存
堆内存被划分成多个大小相等的内存块Region,每个Region是逻辑连续的一段内存。
每个Region被标记了E,S,O,H,说明每个Region在运行时都充当了一种角色,其中H是以往算法中没有的,它代表Humongous,这表示这些Region存储的是巨型对象。当新建对象大小超过Region大小一半的时候,直接在新的一个或者多个连续Region中分配,并标记为H。
3、Region
堆内存中一个Region的大小可以通过-XX:G1HeapRegionSize参数指定,大小区间只能是1M,2M,4M,8M,16M,32M,总之是2的幂次方,如果G1HeapRegionSize为默认值,则在堆初始化时计算Region的实际大小。
默认把堆内存按照2048份均分,最后得到一个合理的大小。
2、GC模式
G1中提供了3种模式垃圾回收模式,young GC,mixed GC和full GC。在不同的条件下被触发
1、young GC
发生在年轻代的GC算法,一般对象(除了巨型对象),都是在eden region中分配内存,当所有的eden region被消耗殆尽无法再申请内存的时候,就会触发一次young GC,这种触发机制和之前的young GC差不多,执行玩一次young GC,活跃对象会被拷贝到survivor region或者晋升到old region中,空闲的region会被放入空闲列表中,等待下次被使用。
参数 | 含义 |
---|---|
-XX:MaxGCPauseMillis | 设置G1收集过程目标时间,默认200ms |
-XX:G1NewSizePercent | 新生代最小值,默认值5% |
-XX:G1MaxNewSizePercent | 新生代最大值,默认值60% |
2、mixed GC
当越来越多的对象晋升到老年代old region时,为了避免堆内存被消耗殆尽,虚拟机会触发一个混合的垃圾收集器,也就是mixed GC;这个算法不是一个old GC,除了回收整个young region,还会回收一部分old region。注:只是一部分老年代,而不是全部老年代,可以选择哪些old region进行收集,从而可以对垃圾回收的耗时时间进行控制。
mixed GC什么时候被触发?
有点类似cms的触发机制 ,如果添加了以下参数:
1 | -XX:CMSInitiatingOccupancyFraction=80 |
当CMS的老年代的使用率达到80%时,就会触发一次cms gc。
相对的,mixed gc中也有一个阈值参数:
1 | -XX:InitiatingHeapOccupancyPercent |
当老年代大小占整个堆大小百分比达到该阈值时,会触发一次mixed gc。
3、mixed GC执行过程
- initial remark:初始标记过程,整个过程STW(Stop-The-World,在执行垃圾回收算法的时候,Java应用程序的其他所有线程都被挂起,Java中一种全局暂停现象,全局停顿,所有Java代码停止,native代码可以执行,但是不饿能够和JVM交互)标记了从GC Root可达的对象
- concurrent marking:并发标记过程,整个过程gc collector线程与应用线程可以并行执行,标记出GC Root可达对象衍生出来的存活的对象,并收集各个Region的存活对象信息。
- remark:最终标记过程,整个过程STW,标记出哪些在并发标记过程中遗漏的,或者内部引用发生变化的对象。
- clean up:垃圾清除过程,如果发现一个Region中没有存活对象,则把该Regioon加入到空闲列表中。
4、full GC
如果对象内存分配速度过快,mixed GC来不及回收,导致老年代old Region被填满,就会触发一次full gc。
G1的full GC算法就是单线程的执行serial old gc,会导致异常长时间的暂停时间,需要进行不断的调优,尽可能的避免full GC。
- 本文作者: Victor Dan
- 本文链接: https://anonymousdq.github.io/victor.github.io/2019/11/01/一、G1垃圾回收器介绍/
- 版权声明: 本博客所有文章除特别声明外,均采用 Apache License 2.0 许可协议。转载请注明出处!