深入浅出JVM(十二)之垃圾回收算法

简介: 深入浅出JVM(十二)之垃圾回收算法

上篇文章深入浅出JVM(十一)之如何判断对象“已死”已经深入浅出的解析JVM是如何评判对象不再使用,不再使用的对象将变成“垃圾”,等待回收

垃圾回收算法有多种,适用于不同的场景,不同的垃圾收集器使用不同的算法

本篇文章将围绕垃圾回收算法,深入浅出的解析垃圾回收分类以及各种垃圾回收算法

垃圾回收算法

垃圾回收分类

垃圾收集器有着多种GC方式,不同的GC方式有自己的特点,回收的堆内存部分也不同

堆内存分为新生代和老年代,新生代存储“年轻”的对象,老年代存储“老”或内存大的对象,对象年龄由经历多少次GC来判断

其中整堆收集时不仅会回收整个堆还会回收元空间(直接内存)

  • 部分收集(Partial GC): 收集目标是部分空间
  • 新生代收集(Minor GC/ Young GC):收集新生代Eden、Survive to、Survive from区
  • 老年代收集(MajorGC/Old GC):收集老年代
  • 混合收集(Mixed GC):收集整个新生代和部分老年代
  • 整堆收集(Full GC): 整个堆 + 元空间

标记-清除算法

Mark-Sweep

标记:从GCRoots开始遍历引用链,标记所有可达对象 (在对象头中标记)

清除:从堆内存开始线性遍历,发现某个对象没被标记时对它进行回收

image.png

标记-清除算法实现简单、不需要改变引用地址,但是需要两次遍历扫描效率不高,并且会出现内存碎片

注意:这里的清除并不是真正意义上的回收内存,只是更新空闲列表(标记这块内存地址为空闲,后续有新对象需要使用就覆盖)

复制算法

Copying

Survive区分为两块容量一样的Survive to区和Survive from区

每次GC将Eden区和Survive from区存活的对象放入Survive to区,此时Survive to区改名为Survive from区,原来的Survive from区改名为Survive to区 保证Survive to区总是空闲的

如果Survive from区的对象经过一定次数的GC后(默认15次),把它放入老年代

流程图

注意:图中的dean为Eden区(写错)

image.png

image.png

注意:最终的survive from区存活对象占用的内存应该是(那两块蓝色)挨着一起的,图中为了标识字分开来了

复制算法不需要遍历,并且不会产生内存碎片,但是会浪费survive区一半的内存,移动对象时需要STW暂停用户线程,并且复制后会改变引用地址(hotspot使用直接指针访问,还要改变栈中reference执行新引用地址)

如果复制算法中对象存活率太高会导致十分消耗资源,因此一般只有新生代才使用复制算法

标记-整理算法

Mark-Compact

标记:从GCRoots开始遍历引用链,标记所有可达对象(在对象头中标记) (与标记-清除算法一致)

整理:让所有存活对象往内存空间一端移动,然后直接清理掉边界以外的所有内存

image.png

标记-整理算法不会出现内存碎片也不会浪费空间,但是效率低(比标记-清除还多了整理功能),移动对象导致STW和改变reference指向

如果不移动对象会产生内存碎片,内存碎片过多,将无法为大对象分配内存

还有种方法:多次标记-清除,等内存碎片多了再进行标记-整理

分代收集算法

标记清除mark-sweep 复制copying 标记整理mark-compact
速度
GC后是否需要移动对象 不移动对象 移动对象 移动对象
GC后是否存在内存碎片 存在内存碎片 不存在内存碎片 不存在内存碎片

需要移动对象 意味着 要改变改对象引用地址 也就是说要改变栈中reference指向改对象的引用地址,并且会发生STW停顿用户线程

当空间中存在大量内存碎片时,可能导致大对象无法存储

分代收集算法 : 对待不同生命周期的对象可以采用不同的回收算法(不同场景采用不同算法)

年轻代: 对象生命周期短、存活率低、回收频繁,采用复制算法,高效

老年代: 对象生命周期长、存活率高、回收没年轻代频繁,采用标记-清除 或混用 标记-整理

增量收集算法

mark-sweep、copying、mark-compact算法都存在STW,如果垃圾回收时间很长,会严重影响用户线程的响应

增量收集算法: 采用用户线程与垃圾收集线程交替执行

增量收集算法能够提高用户线程的响应时间,但存在GC、用户线程切换的开销,降低了吞吐量,GC成本变大

分区算法

堆空间越大,GC时间就会越长,用户线程响应就越慢

分区算法: 将堆空间划分为连续不同的区,根据要求的停顿时间合理回收n个区,而不是一下回收整个堆

每个区独立使用,独立回收,根据能承受的停顿时间控制一次回收多少个区

G1收集器以及两块低延迟收集器Shenandoah、ZGC就使用到这种分区算法

总结

本篇文章围绕垃圾回收算法,深入浅出解析垃圾回收分类、标记清除、复制、标记整理、分代收集、增量收集、分区算法等多种算法

从垃圾回收空间上划分可以分为Full GC回收整个堆加上元空间、Minor GC回收新生代、major GC回收老年代、mixed GC回收新生代加老年代

标记清除算法会遍历引用链标记可达对象从而清理不可达对象,会产生内存碎片,速度一般

复制算法不会产生内存碎片,并且速度很快,但是会浪费survivor区一半空间,并且会移动对象

标记整理算法在标记清理基础上增加整理功能,不会产生内存碎片,但会移动对象,速度慢

不同的算法有不同的特点,应对新生代可以使用复制算法,应对老年代可以使用标签清除/整理算法

增量收集使用GC、用户线程交替执行,虽然降低用户响应,但线程切换、吞吐量下降会增加GC成本

分区算法将堆内存划分为多个区,根据能够接收的停顿时间来回收性价比高的多个区,停顿时间既在能够接收时间内,又能够回收性能比高的区

最后(一键三连求求拉~)

本篇文章将被收入JVM专栏,觉得不错感兴趣的同学可以收藏专栏哟~

本篇文章笔记以及案例被收入 gitee-StudyJavagithub-StudyJava 感兴趣的同学可以stat下持续关注喔~

有什么问题可以在评论区交流,如果觉得菜菜写的不错,可以点赞、关注、收藏支持一下~

关注菜菜,分享更多干货,公众号:菜菜的后端私房菜

相关文章
|
2月前
|
存储 算法 Oracle
极致八股文之JVM垃圾回收器G1&ZGC详解
本文作者分享了一些垃圾回收器的执行过程,希望给大家参考。
|
4天前
|
存储 算法 Java
深入解析 Java 虚拟机:内存区域、类加载与垃圾回收机制
本文介绍了 JVM 的内存区域划分、类加载过程及垃圾回收机制。内存区域包括程序计数器、堆、栈和元数据区,每个区域存储不同类型的数据。类加载过程涉及加载、验证、准备、解析和初始化五个步骤。垃圾回收机制主要在堆内存进行,通过可达性分析识别垃圾对象,并采用标记-清除、复制和标记-整理等算法进行回收。此外,还介绍了 CMS 和 G1 等垃圾回收器的特点。
13 0
深入解析 Java 虚拟机:内存区域、类加载与垃圾回收机制
|
2月前
|
存储 算法 Java
JVM自动内存管理之垃圾收集算法
文章概述了JVM内存管理和垃圾收集的基本概念,提供一个关于JVM内存管理和垃圾收集的基础理解框架。
JVM自动内存管理之垃圾收集算法
|
3月前
|
存储 监控 算法
(六)JVM成神路之GC基础篇:对象存活判定算法、GC算法、STW、GC种类详解
经过前面五个章节的分析后,对于JVM的大部分子系统都已阐述完毕,在本文中则开始对JVM的GC子系统进行全面阐述,GC机制也是JVM的重中之重,调优、监控、面试都逃不开的JVM话题。
|
3月前
|
Java
Jinfo 查看 jvm 配置及使用 Jstat 查看堆内存使用与垃圾回收
Jinfo 查看 jvm 配置及使用 Jstat 查看堆内存使用与垃圾回收
56 5
|
3月前
|
存储 算法 Java
JVM 垃圾回收算法与垃圾回收器
JVM 垃圾回收算法与垃圾回收器
38 3
|
3月前
|
监控 Java 运维
开发与运维收集问题之jstat命令查看JVM垃圾回收情况如何解决
开发与运维收集问题之jstat命令查看JVM垃圾回收情况如何解决
25 1
|
2月前
|
算法 Java 应用服务中间件
探索JVM垃圾回收算法:选择适合你应用的最佳GC策略
探索JVM垃圾回收算法:选择适合你应用的最佳GC策略
|
3月前
|
算法 Java
Java面试题:解释垃圾回收中的标记-清除、复制、标记-压缩算法的工作原理
Java面试题:解释垃圾回收中的标记-清除、复制、标记-压缩算法的工作原理
46 1
|
3月前
|
弹性计算 运维 Java
Serverless 应用引擎使用问题之JVM进行垃圾回收时重启,该如何解决
阿里云Serverless 应用引擎(SAE)提供了完整的微服务应用生命周期管理能力,包括应用部署、服务治理、开发运维、资源管理等功能,并通过扩展功能支持多环境管理、API Gateway、事件驱动等高级应用场景,帮助企业快速构建、部署、运维和扩展微服务架构,实现Serverless化的应用部署与运维模式。以下是对SAE产品使用合集的概述,包括应用管理、服务治理、开发运维、资源管理等方面。
下一篇
无影云桌面