垃圾回收器的发展历程

背景

01、G1解决的问题

G1垃圾回收器是04年正式提出,12开始正式支持,在17年作为JDK9默认的垃圾处理器。

04年的时候,java程序堆的内存越来越大,从而导致程序中可存活的活对象越来越多,因此GCSTW时间越来越长。这是G1要解决的主要问题:STW带来的停顿时间太长了

CMS在此之前效率也很高,但活对象数量一多,STW时间也很长。而且CMS无法解决内存碎片化的问题。

G1还解决的问题是:CMSGC后,无法compact内存。

02、G1达成的目标

(1)减少由于STW而带来的程序延迟时间,做到伪实时、低延时、可设定目标;

可设定目标是指能够设置GC最大STW停顿的时间,G1会尽量达成目的,但不一定达成。

-XX:MaxGCPauseMillis=N

默认情况下是250毫秒

(2)解决CMSGC后,无法压缩程序内存的问题;

(3)在JDK9之后,默认的垃圾处理器就是G1;它适用于堆内存较大的情况下(>4~6G);

G1垃圾回收器

一、G1内存布局

G1不再遵循之前的堆中对象的分代排列,而是将堆分成若干个等大的区域。

而是变成:

默认是分成2048个区域,-XX:G1HeapRegionSize=N 2048

Humongous:当你分配的一个对象超过一半区域的大小时,这个对象就会被放入这个区域。这个区域属于老年代区域。

二、G1的介绍

G1垃圾回收器不再回收整个堆,而是选择一个Collection SetCS)。而且每次GC时,会估计每个Region中的垃圾比例,优先回收垃圾多的Region。这就为什么被叫做Garbage First算法。这也是为什么G1可以控制STW停顿时间的原因。

G1含有三种GC算法:

  • Full young GC:年轻代GC算法:STWParallelCopying
  • 老年代GC算法:Mostly-concurrent markingIncremental compaction
  • Mixed GC:混合GC

三、G1引来的问题

问题描述

G1将年轻代、老年代区域划分为许多个小区域,增加在GC判断对象是否为垃圾的难度。比如:

  • 老年代对象可能持有年代代的引用(跨代引用)
  • 不同的Region间的互相引用

假设在Full young GC时,某个年轻代Region对象可能被老年代的某个对象引用,那么我在回收这个年轻代Region时,怎么知道这里面的对象是否被其他Region、老年代引用呢?

问题解决

Remembered SetCard Table

1、CardTable

每个Region中分为很多区域,每个区域我们成为CardTable,对应的就是上述蓝色区域;每个CardTable有多个entry组成。当对应的内存空间发生改变时,就会标记为dirty

2、RememberedSet

Region1CardTable引用Region2CardTable时,Region2RememberedSet就会记录对应CardTable中的entry,可以根据其找到对应的内存区域。

3、解析

当某个内存对应进行赋值是,就是对象的set方法,我们可以在这种方法上添加dirty的描述。

这其实就是典型的时间换空间的做法:用额外的空间维护引用信息,这就是占用5~10%的过多内存占用。

解决方法的实现

1、Write Barrier介绍

Write barrier是一种向JVM注入的一小段代码,用于记录指针变化。比如说object.field = <reference>

JVM开始更新指针时,就经过以下几步:

  • 标记CardDirty
  • Card存入Dirty Card Queue队列中

这里有一个问题:为什么要放在队列里,而不是直接去更新RememberedSet呢?

这是因为JVM运行可能会有多个线程并行的修改RememberedSet,这样就需要花费额外的时间来解决多线程同步问题。而这种更新引用是频繁的,所以这种额外时间是无法忍受的。

2、Dirty Card Queue

这个队列有白、绿、黄、红四个颜色,表示应用线程往这个队列放任务的状态。

  • White

    表示没有应用线程往队列里放任务,什么事都不用干。

  • Green

    此时Refinement线程开始被激活,开始更新RS-XX:G1ConcRefinementGreenZone=N

  • Yellow

    此时全部的Refinement线程都被激活,来更新RS-XX:G1ConcRefinementYellowZone=N

  • Red

    这个时候,应用线程也开始参与排空队列的工作。-XX:G1ConcRefinementRedZone=N

四、GC算法的过程

1、Fully young GC

GC的过程

(1)STW

此时会暂停所有堆中的对象,将部分Region拷贝到指定区域。

(2)构建Collection Set

fully young GC就是选取所有的EdenSurvivor

(3)扫描GC Roots

(4)更新RememberedSet

排空Dirty Card Queue

(5)Process RS

根据RS找到要GC的对象被哪些对象引用了。

(6)对象拷贝

survivor区域对象的调整。

(7)Reference Processing

额外会做的事

G1记录每个阶段的时间,用于后期自动调优。比如说会记录EdenSurvivor的数量和GC时间,后期会根据我们之前设定的暂停目标来自动调整Region数量。

但是我们设置暂停目标越短,年轻代的Region数量就越少。但这可能会导致Fully young GC频繁发生。

2、Old GC

当堆用量达到一定程度时,就会触发old GC。可以通过以下参数进行设置:

-XX:InitatingHeapOccpancyPercent=45

old GC有一个很大特点就是并发进行的。但它是如何在堆中不断变化的情况下,确定哪些是要清理的垃圾对象呢?

三色标记算法

这种算法实现了在不暂停应用线程的情况下进行并发标记,标记过程过如下:

(1)将GC Root对象记录为黑色,其直接引用对象记录为灰色,并将这些灰色对象放入一个队列中



(2)从队列取出对象,将其标为黑色,将其引用对象记录为灰色,再放入队列中



(3)直到队列中无对象为止

三色标记算法的缺点:Lost Object Problem

三色标记算法并没有完全将所有的活对象都标记出来,这就是Lost Object Problem问题。比如说:

(1)刚开始时

(2)在即将描述将C标为灰色的一刹那

此时,C依然是活对象,但是已经无法将其标记了。

(3)结果

Lost Object Problem的解决

这种解决办法还是通过Write barrier技术来解决。当B.c=null,也就是C指针被删除时,G1还是被认为活对象。

那如果C是新生对象呢?这是老年代GC

Old GC过程

(1)STW

老年代GC会在这个时候,进行一次Fully young GC

(2)恢复应用线程

(3)使用三色标记算法并发标记(init marking

(4)STW

这时候会有一个Remark阶段,主要是解决SATBReference processing

还会有一个Cleanup阶段,用于回收全为空的区

(5)恢复应用线程

3、Mixed GC

我们直到CMS最大的缺点就是无法进行压缩操作,而G1就通过Mixed GC解决了这个问题。

Mixed GC没有固定触发条件,他是根据Fully young GC收集的信息和我们配置的时间来决定,是否触发Mixed GC。它会根据暂停目标,来优先选择垃圾最多的Old Region来执行。

Mixed GC会选择若干个Region进行,默认是选择1/8Old RegionEden RegionSurvivor Region

Mixed GC的过程跟Fully young GC的过程相同,都是:STWParallelCopying

原博客地址

G1垃圾回收器的更多相关文章

  1. 深入浅出具有划时代意义的G1垃圾回收器

    G1诞生的背景 Garbage First(简称G1)收集器是垃圾收集器技术发展历史上的里程碑式的成果,它开创了收集器面向局部收集的设计思路和基于Region的内存布局形式.HotSpot开发团队最初 ...

  2. JVM学习——G1垃圾回收器(学习过程)

    JVM学习--G1垃圾回收器 把这个跨时代的垃圾回收器的笔记独立出来. 新生代:适用复制算法 老年代:适用标记清除.标记整理算法 二娃本来看G1的时候觉得比较枯燥,但是后来总结完之后告诉我说,一定要慢 ...

  3. G1垃圾回收器在并发场景调优

    一.序言 目前企业级主流使用的Java版本是8,垃圾回收器支持手动修改为G1,G1垃圾回收器是Java 11的默认设置,因此G1垃圾回收器可以用很长时间,现阶段垃圾回收器优化意味着针对G1垃圾回收器优 ...

  4. G1 垃圾回收器简单调优

    G1: Garbage First 低延迟.服务侧分代垃圾回收器. 详细介绍参见:JVM之G1收集器,这里不再赘述. 关于调优目标:延迟.吞吐量 一.延迟,单次的延迟 单次的延迟关系到服务的响应时延, ...

  5. 探索G1垃圾回收器

    前言 最近王子因为个人原因有些忙碌,导致文章更新比较慢,希望大家理解,之后也会持续和小伙伴们一起共同分享技术干货. 上篇JVM的文章中我们对ParNew和CMS垃圾回收器已经有了一个比较透彻的认识,感 ...

  6. JAVA之G1垃圾回收器

    概述 G1 GC,全称Garbage-First Garbage Collector,通过-XX:+UseG1GC参数来启用,作为体验版随着JDK 6u14版本面世,在JDK 7u4版本发行时被正式推 ...

  7. jvm默认的并行垃圾回收器和G1垃圾回收器性能对比

    http://www.importnew.com/13827.html 参数如下: JAVA_OPTS="-server -Xms1024m -Xmx1024m -Xss256k -XX:M ...

  8. G1垃圾回收器参数配置

    下面是完整的 G1 的 GC 开关参数列表. 选项/默认值 说明 -XX:+UseG1GC 使用 G1 (Garbage First) 垃圾收集器 -XX:MaxGCPauseMillis=n 设置最 ...

  9. JVM七大垃圾回收器下篇G1(Garbage First)

    G1回收器:区域化分代式 既然我们已经有了前面几个强大的GC,为什么还要发布Garbage First (G1)GC?  原因就在于应用程序所应对的业务越来越庞大.复杂,用户越来越多,没有GC就不能保 ...

随机推荐

  1. # 爬虫连载系列(1)--爬取猫眼电影Top100

    前言 学习python有一段时间了,之前一直忙于学习数据分析,耽搁了原本计划的博客更新.趁着这段空闲时间,打算开始更新一个爬虫系列.内容大致包括:使用正则表达式.xpath.BeautifulSoup ...

  2. 【字节校招】【实习】【内推】字节跳动春招(校招或实习均可)以及日常实习内推ing

    本人是年前刚刚入职抖音的应届生,职业认证还未来的级更改,但是这些都不重要.重要的是我们不能错过优秀的你~ 字节跳动的相关福利我就不介绍了,技术实习生是400/天,房补是1500/月,三餐免费,下午茶, ...

  3. idea最下方视图中没有spring框解决方法

    之前遇到过idea打开一个项目后,如图所示的spring视图框消失不见了. 并且view-Tool windows里面也找不到的问题;因为没有这个的话还挺烦的,网上搜了好久都没有资料,所以记录一下; ...

  4. 简单的scrapy命令和中间件

    创建爬虫 scrapy genspider 名字 xxx.com 运行爬虫 运行名为usnews的爬虫scrapy crawl usnews​运行爬虫文件scrapy runspider quote_ ...

  5. mysql那些事之索引篇

    mysql那些事之索引篇 上一篇博客已经简单从广的方面介绍了一下mysql整体架构以及物理结构的内容. 本篇博客的内容是mysql的索引,索引无论是在面试还是我们日常工作中都是非常的重要一环. 索引是 ...

  6. ssm框架整合---maven工具来导入jar包

    ssm整合 一.导包(pom.xml文件) <?xml version="1.0" encoding="UTF-8"?> <project x ...

  7. Git 的简单使用及ssh配置问题-赖大大

    软件安装 第一步当然是安装啦. 官方网址:https://git-scm.com/ 具体操作 在你本地电脑的文件夹里右击鼠标,选Git base here 显然,你是在本地仓库的master分支上,通 ...

  8. 混合开发 h5+ 沉浸式的适配

    1.需要在mainfest.json plus对象里添加 "statusbar": { "immersed": "true", " ...

  9. docker:一文学基础使用

    目录 docker介绍 安装与镜像源配置 CentOS7 安装 设置镜像源 补充: 简单使用例子 基础概念 四个概念 镜像概念补充: 容器概念补充: 常用命令: 查看docker信息 镜像操作 容器操 ...

  10. [剑指Offer]41.和为S的两个数字 VS 和为S的连续正数序列

    [剑指Offer]41 和为S的两个数字 VS 和为S的连续正数序列 Leetcode T1 Two Sum Given an array of integers, return indices of ...