垃圾回收都是基于分区进行的。G1在实现垃圾回收时一共提供了3种回收的方法,分别是新生代回收(称为Young GC, YGC),混合回收(称为Mixed GC),全回收(称为Full GC, FGC)。这3种垃圾回收触发的时机通常如下:

1. 应用程序分配对象时,发现内存不足,触发YGC;

2. 在YGC执行中,判断整体内存使用是否大于一定的阈值,如果大于启动并发标记;在并发标记完成后,当下一次启动垃圾回收称为Mixed GC,在Mixed GC执行过程中不仅回收新生代分区,同时也回收部分老生代分区;

3. 在用程序分配对象时,发现内存不足,触发YGC或者Mixed GC;垃圾回收结束后再次尝试分配对象,如果内存还不足,此时将触发FGC。

在整个JVM运行过程中,还可以通过外部命令或者代码触发垃圾回收。

1 Young GC概述

G1对于YGC和Mixed GC的回收采用的复制算法。简单可以总结为:从根出发,标记活跃对象,并将活跃对象复制到新的分区中。在实际实现中,G1为了提高回收效率,将整个回收过程进行了细分,大体上拆分为:并行执行部分和串行执行部分。首先G1针对多个根进行并行的标记复制,然后再进行串行的标记复制。最早G1把引用处理也放在串行执行部分中,后来G1对引用处理做了优化,也可以并行执行,但是引用处理并不能直接放入到并行执行部分(因为引用处理必须在多个根并行执行完成之后才能执行)。所以这里把串行执行部分称为其他部分,在其他部分执行中以串行执行为主,有个别的任务的可以并行执行。

YGC的执行顺序来看一下整个收集过程的主要步骤:

1. 进行收集之前需要执行暂停。

2. 选择分区回收集合(称为CSet),对于YGC来说整个新生代分区都会被放入到CSet。

3. 进入并行任务处理

1) 根扫描并处理;处理过程会把根直接引用的对象复制到新的Survivor区,然后把被引用对象的成员变量入栈等待后续的复制处理。

2) 处理老生代分区到新生代分区的引用;首先会把程序运行过程中需要记录的代际关系引用信息进行保存(代际引用关系通过数据结构RSet来存储,G1中还存在单代的引用处理线程),然后从RSet出发,把RSet所在卡表对应的分区内存块中所有的对象都认为是根,把这些根引用到的对象复制到新的Survivor区,然后把被引用对象的成员变量入栈等待后续的复制处理。

3) JIT代码扫描。

4) 根据栈中的对象,进行深度递归遍历复制对象。

4. 下面是其他任务处理,其他任务大部分都是串行执行

1) JIT代码位置更新,在并行任务中已经对代码进行了扫描和复制,这里会更新相关指针所指向的位置。

2) 引用处理,即把引用中使用的存活对象也要复制到新的分区。

3) 字符串去重优化回收,这个是JDK8 G1新引入的功能。是为了优化字符串使用的效率。

4) 清除卡表,就是把全局卡表中已经处理过的分区对应的卡表清空。

5) JIT代码回收,代码已经可以回收,实际上是删除相关的引用。

6) 转移失败处理,主要的工作就是恢复对象头;

7) 引用再处理,把引用中还活着的对象放入到引用队列中,这个是和引用特殊的设计有关。

8) 进行Redirty,这个主要工作就是重构分区对象的引用关系。

9) 释放回收集合CSet中分区对应的内存,即把这些分区放入到自由列表Free List,供后续使用,这里的后续指的是对象分配时如果需要新的分区,可以直接从Free List获取。

10) 尝试大对象回收。

11) 尝试扩展内存,根据内存的使用情况判断是否可以扩展。

12) 调整新生代分区的数目等;主要是根据GC的执行时间和目标停顿时间预测下次可能发生垃圾回收能接受的最大分区数。

2 Mixed GC概述

Mixed GC包括两个部分,并发标记和垃圾回收。当标记完成后,垃圾回收过程和YGC几乎完全相同,唯一的区别就是在回收的时候,不仅仅回收新生代分区,同时还回收一部分老生代分区(可能需要多次混合回收才能把老生代所有的分区回收完成)。所以着重了解一下并发标记的过程。

并发标记是指并发标记线程和应用程序线程同时运行,它有四个典型的子阶段:初始标记子阶段、并发标记子阶段、再标记子阶段和清理子阶段。

(1)初始标记子阶段

负责标记所有从根集合被直接可达的对象,根集合是对象图的起点,初始标记需要将应用程序线程暂停掉,也就是需要暂停一切。在混合回收中的初始标记子阶段和新生代的初始标记几乎一样。实际上混合回收的初始标记子阶段是借用了新生代回收的结果,即新生代垃圾回收后的新生代Survivor分区作为根,所以混合回收一定发生在新生代回收之后,且不需要再进行一次初始标记。这就是所谓的“借道”。

注意实际上除了YGC发生后的Survivor作为并发标记的根之外,并发标记还有一些根是在YGC中识别的。

(2)并发标记子阶段

当YGC执行结束之后,如果发现满足并发标记的条件之后,并发线程就开始进行并发标记。根据新生代的Survivor分区开始并发标记。并发标记的时机是在YGC后,只有内存消耗达到一定的阈值后,才会触发。在G1中这个阈值通过参数InitiatingHeapOccupancyPercent控制(在JDK8中默认值是45,表示的是当已经分配的内存加上本次将分配的内存超过内存总容量的45%就可以开始并发标记,在JDK 11中对这一参数的含义又做了调整)。多个并发标记线程启动,每个线程每次只扫描一个分区,从而标记出存活对象。在标记的时候还会计算存活对象的数量,同时会计算存活对象所占用的内存大小,并计入分区空间。

并发标记子阶段会对所有分区的对象进行标记。这个阶段并不需要STW,故标记线程和应用程序线程并发运行。为了保证并发标记算法的正确,G1使用Snapshot-At-The-Begining(SATB)算法进行并发标记。

(3)再标记子阶段

再标记是最后一个标记阶段。在该阶段中,G1需要暂停一切,找出所有未被访问的存活对象,同时完成存活内存数据计算。引入该阶段的目的,是为了能够达到结束标记的目标。要结束标记的过程,要满足三个条件:

  • 从根(Survivor)出发并发标记子阶段已经标记出所有的存活对象。

  • 标记栈是空的。

  • 所有的引用变更对象都被处理了;这里的引用变更对象包括新增空间分配的对象和引用变更对象,新增空间所有对象都认为是活跃的(即便是对象已经死亡也没有关系,在这种情况下只是增加了一些浮动垃圾),引用变更处理的对象通过一个队列记录,在该子阶段会处理这个队列中所有的对象。

(4)清理子阶段

再标记子阶段之后是清理子阶段,该子阶段也需要暂停一切。清理子阶段主要执行以下操作:

  • 统计存活对象,统计的结果将会用来排序分区,以用于下一次的垃圾回收时分区的选择。

  • 交换标记位图,为下次并发标记准备。

  • 把空闲分区放到空闲分区列表中;这里的空闲分区指的是全都是垃圾对象的分区;如果分区还有任何活跃对象都不会释放,真正释放的动作是在混合回收中。

该阶段比较容易引起误解的地方在于,清理子阶段并不会清理垃圾对象,也不会执行存活对象的拷贝。也就是说,在极端情况下,该阶段结束之后,空闲分区列表将毫无变化,JVM的内存使用情况也毫无变化。

YGC和Mixed GC是G1种最为常见的垃圾回收方式,整个G1垃圾回收的活动图如图所示。

3 Full GC概述

FGC是整个程序运行过程中需要尽量避免发生。FGC的发生将导致应用程序停顿时间不可控。所以这里简单的介绍一下FGC。

FGC采用的标记清除算法,在JDK10之前,G1的FGC采用的串行实现,从JDK10开始,FGC被优化成并行执行。串行和并行的实现基本类似,唯一的不同是,在串行执行时标记清除是针对整个内存,而在并行执行时,多个并行执行的线程按照分区来标记清除。

标记清除算法,主要分为4步:

1. 标记活跃对象。

2. 计算新对象的地址。

3. 把所有的引用都更新到新的地址上。

4. 移动对象。

4 G1中Top10参数

在JDK8中G1共有41个可配置的生成参数,可以在JVM启动时调整相关的参数从而保证JVM运行达到最优。这里提供工作中最常用的10个参数:

  • G1HeapRegionSize,设置分区大小。

  • G1ReservePercent,设置保留空间,用于YGC时对象晋升时使用。

  • ParallelGCThreads,设置垃圾回收时并行工作线程的个数。

  • G1ConcRefinementThreads,设置并发引用工作线程的个数。

  • ConcGCThreads,设置并发工作线程的个数。

  • InitiatingHeapOccupancyPercent,设置并发标记启动的条件。

  • G1MixedGCCountTarget,设置混合回收时,一次回收老生代分区的比例。

  • G1HeapWastePercent,判断是否启动混合回收,当回收分区集合中可用的内存大于该比例才会被启动。

  • G1UseConcMarkReferenceProcessing,是否允许并行的处理引用

  • G1MixedGCLiveThresholdPercent,设置混合回收时,当分区中可用的内存大于该比例才会被回收

关于初始标记中根的介绍、并发标记的SATB算法以及参数的具体介绍可以参考《JVM G1源码分析和性能调优》。

推荐语:资深Java工程师撰写,来自一线实践经验的结晶,详细分析G1的基本运行原理以及调优方法,讲解细腻,图示丰富,可帮助Java工程师深入理解垃圾回收技术

点击链接了解详情并购买

关于作者: 彭成寒 高级Java工程师,目前主要从事风控系统设计、算法建模、大数据处理等工作。有超过10年的Java和C++开发经验。

文末彩蛋来袭

更多精彩回顾

书单 | 5月书讯 | 华章IT图书上新啦!重磅新书在线投喂...

干货 | 73页PPT,教你从0到1构建用户画像系统(附下载)
榜单 | 423世界读书日 | 华章精品IT书单独家推荐

收藏 | 这10本书助你从容应对数字化转型中可能出现的各种挑战

G1垃圾回收算法概述相关推荐

  1. 什么是G1垃圾回收算法

    转载自 什么是G1垃圾回收算法 为解决CMS算法产生空间碎片和其它一系列的问题缺陷,HotSpot提供了另外一种垃圾回收策略,G1(Garbage First)算法,通过参数 -XX:+UseG1GC ...

  2. 【JVM】垃圾回收算法与分代回收

    文章目录 1. 垃圾回收算法概述 2. 标记-清除算法 3. 标记-复制算法 4. 标记-整理算法 5. 分代回收 本文参考:深入理解Java虚拟机:JVM高级特性与最佳实践(第3版) 1. 垃圾回收 ...

  3. JVM 垃圾回收算法与ART CC回收器实现概述

    前言 在作者的上一篇文章<Android R常见GC类型与问题案例>中,对Demo应用的Heap堆结构与Space类型及相对应内存分配算法做了简要的探究,同时对Android R机器运行中 ...

  4. 垃圾回收概述(垃圾回收算法)

    垃圾回收概述 Java 和 C++语言的区别,就在于垃圾收集技术和内存动态分配上,C++语言没有垃圾收集技术,需要程序员手动的收集. 垃圾收集,不是Java语言的伴生产物.早在1960年,第一门开始使 ...

  5. JVM学习笔记(二):垃圾回收、垃圾回收算法、垃圾回收器(Serial、Parallel、CMC、G1)、内存分配原则实战

    垃圾回收 一.判断对象是否可以被回收 1.引用计数计数法 内容:在对象中添加一个引用计数器,每当有一个地方引用它,计数器就加一:当引用失效时,计数器就减一:任何时刻计数器为零的对象都是不可能在被使用的 ...

  6. 【11-JVM面试专题-说说你知道的垃圾回收算法?垃圾回收器你知道吗?CMS、G1和ZGC垃圾回收器你有过了解吗?】

    JVM面试专题-说说你知道的垃圾回收算法?垃圾回收器你知道吗?CMS.G1和ZGC垃圾回收器你有过了解吗? JVM面试专题-说说你知道的垃圾回收算法?垃圾回收器你知道吗?CMS.G1和ZGC垃圾回收器 ...

  7. 2、垃圾回收算法(标记清除算法、复制算法、标记整理算法和分代收集算法),各种垃圾收集器讲解(学习笔记)

    2.垃圾回收概述 2.1.垃圾回收算法 2.1.1.垃圾回收算法-标记清除算法 2.1.2.垃圾回收算法–复制算法 2.1.3.垃圾回收算法–标记整理算法和分代收集算法 2.1.4.垃圾回收算法–Se ...

  8. 22-09-02 西安 JVM 类加载器、栈、堆体系、堆参数调优、GC垃圾判定、垃圾回收算法、对象的finalize机制

    这篇文章不少地方都截图了宋红康老师的课件,实在他jvm这块讲的真好.连接地址如下: 尚硅谷宋红康JVM全套教程(详解java虚拟机)_哔哩哔哩_bilibili JVM入门 1.JVM结构图 JVM是 ...

  9. JVM底层原理+四大垃圾回收算法详解-周阳老师

    转载自,感谢原作者:https://www.jianshu.com/p/9e6841a895b4 注意:垃圾回收算法周阳老师讲的有错误,具体在p19,四大垃圾回收算法为复制算法.标记-整理算法.标记- ...

最新文章

  1. Linux原始套接字实现分析---转
  2. UVM基础之------uvm_port_base
  3. php mysql 统计_PHP和MySQL实现优化统计每天数据
  4. Unreal Engine 4 —— 使用ProceduralMeshComponent实现模型实时切割
  5. ios9 字符串与UTF-8 互相转换
  6. classnotfoundexception是什么异常_大佬说“异常信息”是优秀程序员编写代码的宝贵财富,这是真的吗...
  7. python操作rabbitmq操作数据
  8. 计算机缺失esul.dll,msedgeupdateres_es.dll
  9. ocr tesseract_OCR引擎之战— Tesseract与Google Vision
  10. 《动态壁纸 : 手机壁纸大全》EULA条款协议
  11. 【Cactus仙人掌图】仙人掌基础知识学习笔记
  12. 小白必学的Ps火焰字制作教程
  13. java 室内3d_室内地图制作-首款实时室内绘制室内地图-3D室内地图
  14. 屏蔽拼多多广告信息的方法
  15. 一张图帮你看懂 iPhone 6 Plus 的屏幕分辨率
  16. 微信公众号模板消息推送(PHP)
  17. 【Javaweb】基础开发流程与介绍
  18. tensorflow的early stopping模型保存方式
  19. 魔兽世界最新服务器推荐,[大陆]《魔兽世界》全新第六大区推荐服务器
  20. 全球液晶面板供应紧张推动价格上涨,中国面板企业再迎高光时刻

热门文章

  1. 武汉星起航:万圣节来临,星起航自营教你选品
  2. PHPChina学院jQuery Mobile与Phone
  3. 基于LabVIEW网络的虚拟测控实验系统设计
  4. 《Blender建模练习:人物模型多边形建模》
  5. 百度音乐 android,Android 百度音乐 - CNMO
  6. ubuntu突然断电重启显卡驱动失败解决办法(不需要重装驱动)
  7. R数据可视化第三弹---ggplot2和REmap包绘制地图
  8. 计算机开机跳过硬盘检查,快速取消Win7电脑开机自动检测硬盘的五大妙招
  9. CVX用户指南之基础
  10. 关于近日MS08067实验室被盗课、拼课的声明