G1垃圾收集器介绍

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了G1垃圾收集器介绍相关的知识,希望对你有一定的参考价值。

参考技术A 为解决CMS算法产生空间碎片和其它一系列的问题缺陷,HotSpot提供了另外一种垃圾回收策略,G1(Garbage First)算法,通过参数 -XX:+UseG1GC 来启用,该算法在JDK 7u4版本被正式推出,官网对此描述如下:

G1垃圾收集算法主要应用在多CPU大内存的服务中,在满足高吞吐量的同时,竟可能的满足垃圾回收时的暂停时间,该设计主要针对如下应用场景:

1、以往的垃圾回收算法,如CMS,使用的堆内存结构如下:

这些space必须是地址连续的空间。

2、在G1算法中,采用了另外一种完全不同的方式组织堆内存,堆内存被划分为多个大小相等的内存块(Region),每个Region是逻辑连续的一段内存,结构如下:

每个Region被标记了E、S、O和H,说明每个Region在运行时都充当了一种角色,其中H是以往算法中没有的,它代表Humongous,这表示这些Region存储的是巨型对象(humongous object,H-obj),当新建对象大小超过Region大小一半时,直接在新的一个或多个连续Region中分配,并标记为H。

堆内存中一个Region的大小可以通过 -XX:G1HeapRegionSize 参数指定,大小区间只能是1M、2M、4M、8M、16M和32M,总之是2的幂次方,如果G1HeapRegionSize为默认值,则在堆初始化时计算Region的实践大小,具体实现如下:

默认把堆内存按照2048份均分,最后得到一个合理的大小。

G1中提供了三种模式垃圾回收模式,young gc、mixed gc 和 full gc,在不同的条件下被触发。

发生在年轻代的GC算法,一般对象(除了巨型对象)都是在eden region中分配内存,当所有eden region被耗尽无法申请内存时,就会触发一次young gc,这种触发机制和之前的young gc差不多,执行完一次young gc,活跃对象会被拷贝到survivor region或者晋升到old region中,空闲的region会被放入空闲列表中,等待下次被使用。

当越来越多的对象晋升到老年代old region时,为了避免堆内存被耗尽,虚拟机会触发一个混合的垃圾收集器,即mixed gc,该算法并不是一个old gc,除了回收整个young region,还会回收一部分的old region,这里需要注意:是一部分老年代,而不是全部老年代,可以选择哪些old region进行收集,从而可以对垃圾回收的耗时时间进行控制。

那么mixed gc什么时候被触发?

先回顾一下cms的触发机制,如果添加了以下参数:

当老年代的使用率达到80%时,就会触发一次cms gc。相对的,mixed gc中也有一个阈值参数 -XX:InitiatingHeapOccupancyPercent ,当老年代大小占整个堆大小百分比达到该阈值时,会触发一次mixed gc.

mixed gc的执行过程有点类似cms,主要分为以下几个步骤:

如果对象内存分配速度过快,mixed gc来不及回收,导致老年代被填满,就会触发一次full gc,G1的full gc算法就是单线程执行的serial old gc,会导致异常长时间的暂停时间,需要进行不断的调优,尽可能的避免full gc.

jdk11新特性——新的Epsilon垃圾收集器

目录

一、Epsilon垃圾收集器概述

  • A NoOp Garbage Collector
  • JDK上对这个特性的描述是: 开发一个处理内存分配但不实现任何实际内存回收机制的GC, 一旦可用堆内存用完, JVM就会退出。
  • 如果有System.gc()调用, 实际上什么也不会发生(这种场景下和-XX:+DisableExplicitGC效果一样), 因为没有内存回收, 这个实现可能会警告用户尝试强制GC是徒劳。

二、Epsilon垃圾收集器用法

  • 再 VM options选项中配置 -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC,如下图:

三、Epsilon垃圾收集器代码示例

  • 示例代码

    package com.xz.jdk11.day1;
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * @description:
     * @author: xz
     */
    public class EpsilonTest 
        public static void main(String[] args) 
            boolean flag = true;
            List<Garbage> list = new ArrayList<>();
            long count = 0;
            while (flag) 
                list.add(new Garbage());
                if (count++ ==100) 
                    list.clear();
                    count++;
                
            
            System.out.println("程序结束");
        
    
    
    class Garbage 
        //这个方法是GC再清除本对象时,会调用一次
        @Override
        public void finalize() 
            System.out.println(this + "垃圾收集");
        
    
    
  • 运行,输出结果如下:

  • 由上图输出结果可知,使用选项 -XX:+UseEpsilonGC, 程序很快就因为堆空间不足而退出。

四、使用Epsilon垃圾收集器的原因

  • 提供完全被动的GC实现,,具有有限的分配限制和尽可能低的延迟开销,但代价是内存占用和内存吞吐量。
  • java实现可广泛选择高度可配置的GC实现。各种可用的收集器最终满足不同的需求,,即使它们的可配置性使它们的功能相交。 有时更容易维护单独的实现,,而不是在现有GC实现上堆积另一个配置选项。

五、使用Epsilon垃圾收集器的主要用途

  • 性能测试(它可以帮助过滤掉GC引起的性能假象)
  • 内存压力测试(例如,知道测试用例 应该分配不超过1GB的内存, 我们可以使用-Xmx1g –XX:+UseEpsilonGC, 如果程序有问题, 则程序会崩溃)
  • 非常短的JOB任务(对象这种任务, 接受GC清理堆那都是浪费空间)
  • VM接口测试
  • Last-drop 延迟&吞吐改进

以上是关于G1垃圾收集器介绍的主要内容,如果未能解决你的问题,请参考以下文章

深入解析G1垃圾收集器与性能优化

G1垃圾收集器深度剖析

G1垃圾收集器入门

JVM技术专题 深入理解G1垃圾收集器的原理和运行机制「原理分析篇」

JVM垃圾回收篇(经典垃圾回收器讲解)

JVM垃圾回收篇(经典垃圾回收器讲解)