JAVA的平凡之路——此峰乃是最高峰JVM-GC垃圾回收器(1)-06

一、是什么

1、概念

垃圾回收器是一种自动内存管理机制,它主要职责追踪在使用的对象,和回收不再使用的对象,及时把内存块归还系统,以便后续分配。

2、垃圾回收器算法

(1)分代收集理论

按照对象的生命周期,分成年轻代和老年代,新生代再分为eden区、s1、s2三块区域。

(2)标记-复制算法

把内存等分成两块,然后一块存入对象,另一块闲置,当垃圾收集时,先标记幸存对象,然后复制幸存对象到闲置区域,然后清空原有区域,然后反复如此进行垃圾回收。

缺点:浪费内存空间,对于大对象来说,来回复制资源浪费严重,所以比较适用于年轻代

3、主要的垃圾回收器

Serial、Serial Old 、ParNew、CMS、Parallel、Parallel Old、G1、ZGC等等

二、为什么

1、垃圾回收的原因

c语言代码在编写时需要手动去释放对象使用,否则对象会一直占用内存空间,类似像java的流操作一样,你不关闭连接,就会一直保持,但是java相对智能,依赖JVM对对象进行管理。

2、gcroot可达性算法

从线程中的局部变量表的变量入手作为root节点一路查下去进行标记,所有关联的对象引用都被认为是幸存对象。

3、三色标记

(1)黑

本对象和子对象都标记

(2)灰

本对象已标记,但是引用对象存在未标记情况

(3)白

未访问/未标记,初始标记时默认白色

三、深究

1、漏标

满足下列两种情况

(1)黑色a对象新增了对c对象的引用

(2)灰色b对象山删除了对c对象的引用

这两种情况都是在并发标记情况下出现的,初始标记 STW完以后,并发标记时用户线程会对数据继续操作,会导致出现上述情况,已经扫描过的a对象新增了相关引用,因为a对象已经是黑色所以再扫描时,就不会再扫描。

灰色b对象删除了对c对象引用,因为它是灰色对象所以重新标记时,会扫描发现c对象不可达然后c对象会被删除。

为什么需要同时满足两个情况呢,因为并发标记时有个机制,就是新产生的引用会默认标记黑色,所以只有这种本身存在,新建了联系无法重新标记处理,但是旧的联系又可以通过重新标记进行处理。

2、卡表、记忆集

卡表和记忆集的关系类似于HashMap和Map的关系

记忆集:分代概念是基础,记忆集是抽象概念,但是在G1中对记忆集进行了细化,G1中的每一个Region都维护一个记忆集,记录着每一个对象跨 Region引用关系,通过写屏障来维护。

卡表:老年代会维护一个卡表,记录这个每一个跨代使用的对象关系,也是通过写屏障来完成。

3、写屏障、增量更新、原始快照

写屏障:类似于 aop的概念切面,在执行逻辑前后增加写入逻辑, 按照前后可以分为前写屏障和后写屏障,根据操作前的数据信息操作都是前写屏障例如G1的原始快照 需要操作前保留原有需要删除的引用,根据操作后的数据信息操作都是例如 G1的记忆集和CMS的卡表更新。

增量更新:是为了解决漏标,针对漏标满足的第一条件,黑对象,增加了白对象的引用,为了避免忽略新增引用扫描,会记录到卡表,卡表引用会记录位脏卡,重新标记的时候根据卡表脏卡重新扫描。

原始快照:也是为了解决漏标,针对漏标满足的第二条件,灰对象删除了白对象,通过前写屏障SATB写入需要删除的引用,标记删除引用对象, 等待G1最终标记扫描,会产生多余浮动垃圾。

G1和CMS:

g1使用的原始快照,cms使用的增量更新,cms使用增量更新是他可以通过卡表在重新扫描时可以重新扫描,但是g1不可以,他只能维护单独快照来维护。

相关推荐
leaves falling9 分钟前
C++类和对象(1)
开发语言·c++
2401_8732046513 分钟前
模板编译期循环展开
开发语言·c++·算法
2501_9454235415 分钟前
工具、测试与部署
jvm·数据库·python
Oueii16 分钟前
数据分析师的Python工具箱
jvm·数据库·python
我真会写代码16 分钟前
深度解析并发编程锁升级:从偏向锁到重量级锁,底层原理+面试考点全拆解
java·并发编程·
Meepo_haha22 分钟前
创建Spring Initializr项目
java·后端·spring
weixin_4219226922 分钟前
使用Scikit-learn进行机器学习模型评估
jvm·数据库·python
会编程的土豆22 分钟前
C++中的 lower_bound 和 upper_bound:一篇讲清楚
java·数据结构·算法
Memory_荒年23 分钟前
SpringBoot事务源码深度游:从注解到数据库的“奇幻漂流”
java·后端·spring