一、是什么
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不可以,他只能维护单独快照来维护。

被折叠的 条评论
为什么被折叠?



