GC垃圾回收之CMS、G1
发布日期:2021-06-30 21:30:25 浏览次数:2 分类:技术文章

本文共 3016 字,大约阅读时间需要 10 分钟。

前瞻:

回收算法:

  • 引用计数法:每个对象都有一个存储被引用次数的计数器,为0表示可以被回收,优点快,缺点是2个对象相互引用无法回收。
  • 根搜索法:通过GCroots(根对象)向下查找被应用的对象,回收未被引用的。

GC ROOT对象包括:

  • 虚拟机(JVM)栈中引用对象
  • 方法区中的类静态属性引用对象
  • 方法区中常量引用的对象(final 的常量值)
  • 本地方法栈JNI的引用对象

三色标记法

用于标记JVM中的对象状态。

  • 白:表示对象未被扫描,如果标记结束后还为白色,则会被回收。
  • 黑:表示对象已被扫描,表示被“gc root”引用,不会被回收。
  • 灰:表示对象正在扫表,表示从上级扫描到了它,但还未扫描它的下级对象,扫描完成会变为黑。

STW

stop the world,暂停虚拟器,暂停其他用户线程,只有GC现场运行,程序处于暂停状态。

 

年轻代回收器

一般使用采用复制收集算法,一个字快。

  • Serial收集器:一个单线程收集器,在进行回收的时候,必须暂停其他所有的工作线程,直到收集结束。缺点:因为要完全暂停线程,所以用户体验不佳。但是由于新生代回收得较快,所以停顿的时间非常少,而且没有线程切换的开销,因此也简单高效。通过-XX:+UseSerialGC参数启用。
  • ParNew收集器:这个是Serial收集器的多线程版本,适用于多核CPU的设备。但对于单核的设备来说,需要进行线程之间的切换,效率反而没有单线程的高。通过-XX:ParallelGCThreads参数限制收集的线程数,-XX:+UseParNewGC参数启用。
  • Parallel Scavenge收集器:该收集器是默认年轻代收集器。他的关注点和其他的收集器不同,其他的关注点是尽可能的缩短Full GC的时间。而该收集器关注的是一个可控的吞吐量。吞吐量=运行代码的时间/(运行代码的时间+GC的时间),通过参数-XX:MaxGCPauseMillis设置最大GC的停顿时间和-XX:GCTimeRatio 设置吞吐量的大小。-XX:+UseParallelGC参数启用。主要适合在后台运算而不需要太多交互的任务。

CMS

全称Concurrent Mark and Sweep,并发标记清理回收器,用于对年老代进行回收,目标是尽量减少应用的暂停时间,减少full gc发生的机率,利用和应用程序线程并发的垃圾回收线程来标记清除年老代。CMS并非没有暂停,而是用两次短暂停来替代串行标记整理算法的长暂停。

  • 过程
  1. 初始标记(STW initial mark) :需要stop the world,暂停其他用户线程,CMS单线程从”根对象”开始查找,标记能够和”根对象”关联的年老代对象,包括通过年轻代关联的年老代对象,只标记一级,为了减少stop时间。
  2. 并发标记(Concurrent marking) :和用户线程并发处理,在初始标记的对象基础上,向下标记所有关联对象。
  3. 并发预清理(Concurrent precleaning): 和用户线程并发处理,对于在并发标记阶段发生变化的对象进行标记,并对它的后续关联对象进行标记。
  4. 重新标记(STW remark) :需要stop the world,标记哪些从”根对象”开始查找未被标记的对象。因为之前的并发标记过程中用户现场可能创建或改变了对象关系,需要重新标记哪些改动。
  5. 并发清理(Concurrent sweeping) :和用户线程并发处理,清理未被引用的对象。
  6. 并发重置(Concurrent reset):重置CMS的内置数据结构,等待下一次回收。

  • 缺点
  1. 内存空间分散:为减少回收时间,没有对内存进行整理,导致内存空间分散,CMS将分散的内存空间记录在一张表中,JVM分配对象时,根据对象大小在内存空间表中找出可存下的内存空间,如果没有则出发GC操作。
  2. 需要更多CPU资源:并发需要一直占用一个CPU,为提高回收速度,需要更快的CPU。
  3. 需要更大堆空间:为了在GC时,其他线程还能执行,需要预留一定的空间,所有GC出发一般会设置当内存占用到一定比例时出发回收。
  • 使用场景
  1. 如果你的应用程序对停顿比较敏感,并且服务器的内存和CPU足够强大。
  2. 如果在JVM中有相对较多存活时间较长的对象(老年代比较大)会更适合使用CMS。

G1

全称Garbage First,可用于年轻代和年老代,堆被划分成 许多个连续的区域(region)。每个区域大小相等,在1M~32M之间。JVM最多支持2000个区域,可推算G1能支持的最大内存为2000*32M=62.5G。区域(region)的大小在JVM初始化的时候决定,也可以用-XX:G1HeapReginSize设置。

过程

Mixed GC(混合GC)主要可以分为两个阶段:

1、全局并发标记(global concurrent marking)
全局并发标记又可以进一步细分成下面几个步骤:

  • 初始标记(initial mark,STW)。它标记了从GC Root开始直接可达的对象。初始标记阶段借用young GC的暂停,因而没有额外的、单独的暂停阶段。
  • 并发标记(Concurrent Marking)。这个阶段从GC Root开始对heap中的对象标记,标记线程与应用程序线程并行执行,并且收集各个Region的存活对象信息。过程中还会扫描上文中提到的SATB write barrier所记录下的引用。
  • 最终标记(Remark,STW)。标记那些在并发标记阶段发生变化的对象,将被回收。
  • 清除垃圾(Cleanup,部分STW)。这个阶段如果发现完全没有活对象的region就会将其整体回收到可分配region列表中。 清除空Region。

2、拷贝存活对象(Evacuation)

Evacuation阶段是全暂停的。它负责把一部分region里的活对象拷贝到空region里去(并行拷贝),然后回收原本的region的空间。Evacuation阶段可以自由选择任意多个region来独立收集构成收集集合(collection set,简称CSet),CSet集合中Region的选定依赖于上文中提到的停顿预测模型,该阶段并不evacuate所有有活对象的region,只选择收益高的少量region来evacuate,这种暂停的开销就可以(在一定范围内)可控

G1的垃圾回收过程是和应用程序并发执行的,当Mixed GC的速度赶不上应用程序申请内存的速度的时候,Mixed G1就会降级到Full GC,使用的是Serial GC。Full GC会导致长时间的STW,应该要尽量避免。

导致G1 Full GC的原因可能有两个:

  1. 没有足够的空间存放晋升的对象;
  2. 并发处理过程完成之前空间耗尽。

ZGC

全程Z Garbage Collector,Java 11包含的一个全新垃圾收集器,在G1垃圾回收器的历年基础上引入大量新技术,实现快速GC。对于TB级的大堆也能处理,速度是G1的上百倍,还在试用阶段,稳定后再做学习。

目标:

  • 停顿时间不超过10ms
  • 停顿时间不随heap大小或存活对象大小增大而增大
  • 可以处理从几百兆到几T的内存大小

使用技术包括:

  • 并发标记:减少stop the world
  • 着色指针:
  • 多重映射:
  • 读屏障:
  • 重定位:
  • 分区:
  • 压缩:

转载地址:https://lizz6.blog.csdn.net/article/details/103154155 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:Spring之事物传播原理
下一篇:JDK源码之HashMap与ConcurrentHashMap区别

发表评论

最新留言

哈哈,博客排版真的漂亮呢~
[***.90.31.176]2024年04月28日 06时13分04秒