垃圾回收器的发展历程

背景

01、G1解决的问题

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

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

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

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

02、G1达成的目标

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

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

-XX:MaxGCPauseMillis=N

默认情况下是250毫秒

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

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

G1垃圾回收器

一、G1内存布局

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

而是变成:

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

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

二、G1的介绍

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

G1含有三种GC算法:

  • Full young GC:年轻代GC算法:STW、Parallel、Copying
  • 老年代GC算法:Mostly-concurrent marking、Incremental compaction
  • Mixed GC:混合GC

三、G1引来的问题

问题描述

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

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

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

问题解决

Remembered Set、Card Table

1、CardTable

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

2、RememberedSet

当Region1的CardTable引用Region2的CardTable时,Region2的RememberedSet就会记录对应CardTable中的entry,可以根据其找到对应的内存区域。

3、解析

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

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

解决方法的实现

1、Write Barrier介绍

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

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

  • 标记Card为Dirty
  • 将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就是选取所有的Eden和Survivor。

(3)扫描GC Roots

(4)更新RememberedSet

排空Dirty Card Queue

(5)Process RS

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

(6)对象拷贝

survivor区域对象的调整。

(7)Reference Processing

额外会做的事

G1记录每个阶段的时间,用于后期自动调优。比如说会记录Eden、Survivor的数量和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阶段,主要是解决SATB、Reference processing

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

(5)恢复应用线程

3、Mixed GC

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

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

Mixed GC会选择若干个Region进行,默认是选择1/8的Old Region、Eden Region、Survivor Region。

Mixed GC的过程跟Fully young GC的过程相同,都是:STW、Parallel、Copying。

原博客地址

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. javascript的“好莱坞原则”

    好莱坞原则——不要给我们打电话,我们会给你打电话(don‘t call us, we‘ll call you).在Javascript中就是:别调用我们,我们会调用你. “好莱坞原则”强调的是高层对低 ...

  2. xcode制作越狱包

    1.将运行目标选为iOS Device 2.Edit Scheme -> 选择 Run [App Name] -> Build Configuration下拉框中选择Release 3.生 ...

  3. LoadRunner 11破解方法:

    LoadRunner 11破解方法: 请严格安装顺序操作! a.用LR8.0中的mlr5lprg.dll.lm70.dll覆盖LR11安装目录下“bin”文件夹中的对应文件: b.运行deleteli ...

  4. h5 移动端适配方案思考

    基础概念 CSS像素(CSS pixels) 这个是浏览器使用的抽象单位,用来精确度量网页上的内容.平时经常写的width:100px;height:100px;都是与设备无关的. 设备独立像素(de ...

  5. 使用VS2017进行Python代码的编写并打印出九九乘法表

    我们来盘一盘怎么使用VS2017进行python代码的编写并打印出九九乘法表. 使用Visual Studio 2017进行Python编程不需要太复杂的工作,只需要vs2017安装好对Python的 ...

  6. java之AQS和显式锁

    本次内容主要介绍AQS.AQS的设计及使用.ReentrantLock.ReentrantReadWriteLock以及手写一个可重入独占锁 1.什么是AQS? AQS,队列同步器AbstractQu ...

  7. Linux服务器(Centos)上安装jexus

    哈子是Jexus Jexus是一款Linux平台上的高性能WEB服务器和负载均衡网关,Jexus Web Service,简称JWS,以支持ASP.NET.ASP.NET CORE.PHP为特色, 同 ...

  8. 是时候了解Java Socket底层实现了

    在Java中,提供了一系列Socket API,可以轻松建立两个主机之间的连接.读取数据,那底层到底怎么实现,很少人去关心.这其实最终还是通过调用操作系统提供得Socket接口完成(TCP/IP是由操 ...

  9. CSRF和XSS区别和预防

    名词解释 CSRF(Cross-site request forgery)跨站请求伪造 XSS (Cross-site scripting)跨站脚本攻击,这里缩写css被前端层叠样式表(Cascadi ...

  10. [SQL]3.26--175+176+177+178+180+181+182

    175.组合两个表 题目 Code SELECT FirstName, LastName, City, State FROM Person LEFT JOIN Address --由于需要Person ...