5、垃圾收集器

本文详细介绍了Java中的几种垃圾收集器,包括Serial、Parallel、ParNew、CMS和G1,它们各自的特点、适用场景以及GC的各个阶段。重点讨论了并发标记过程中的多标和漏标问题以及解决方案,如写屏障技术,并提到了安全点和安全区域在垃圾收集中的作用。
摘要由CSDN通过智能技术生成

serial parallel parNew cms g1 全是分代思想的实现者,所以分代思想的优化方式都是通用的,标记算法全是可达性算法实现。

serial

单线程实现,整个gc过程会STW

回收算法使用标记整理

适合单CPU 小内存,1G以内

年轻代 serial 老年代 serial old

parallel

多线程实现,整个gc过程会STW

回收算法使用标记整理

适合多cpu 小内存,1-4G

年轻代 parallel 老年代 parallel old

parNew

同parallel一样的实现, 存在是因为parallel无法和cmd配合使用,所以就开发一个可以和cms配合的parallel,命名为parNew

仅用于年轻代

cms

concurrent mark sweep 并发标记 分多阶段回收,仅部分阶段会STW, 注重用户体验

回收算法使用标记删除,删除快,但需要内存碎片整理

适合大内存4-8G

GC各阶段:

1、初始标记 stw 标记gcroot直接引用对象,第一层

2、并发标记 遍历上阶段标记的对象所有引用

3、重新标记 stw 处理并发时,多标漏标的对象

4、并发清理 删除标记对象

5、并发重置

多标与漏标

在并发标记阶段,标记和用户线程是并行的,引用的重新赋值会产生多标漏标问题。

1、若已经标记的对象被赋值为null,按正常来说应该被回收,但是却已经被标记过了,称为多标,多标不会对系统产生影响,等待下次gc即可。

2、若黑色对象内部赋值了新的引用, 由于黑色对象不会被遍历,新引用对象就会漏掉,若新引用对象是白色,则可能被删除,产生严重bug,必须处理。

漏标处理,写屏障-增量更新, 在用户赋值时,将新对象加入容器,等待重新标记。

内存整理,由于是标记删除,会产生碎片,需要进行内存整理,默认每次gc后整理,可配置n,在n次后进行整理。内存整理是stw。

一边gc,一边运行系统,当上一次还没完,又触发gc后,就会stw, 使用serial old stw进行垃圾收集。

g1

使用了region模式,默认划分了2048个region,分代仅是逻辑概念, 物理分区不再按照分代思想。新增了Humongous类型分区,专门用于存放超过50%region的大对象,在mixed/full gc中清理。每个region的类型是动态的可以是eden survive old humongous等

通过-XX:G1NewSizePercent设置年轻代占比(默认5%)年轻代会根据gc动态增长,最大值通过-XX:G1MaxNewSizePercent设定,默认60%。e区和s区比例不变。年轻代老年代的转移仍然按照分代思想, 除了大对象外。

采用标记复制算法,每个region独立回收。回收策略会根据参数-XX:MaxGCPauseMillis(期望的STW时间ms)来制定。

适合8G以上的内存

GC各阶段

1、初始标记, 同cms,stw,标记gcroot直接引用对象

2、并发标记,同cms

3、最终标记,同cms并发标记,stw

4、筛选回收,stw,对各region进行回收评估,选择满足期望STW时间的region回收,将region内存活对象转移到新的region。由于采用的是复制算法,必须stw,不同于cms。

收集器内部会对每个region评估收集耗时(通过内存大小,对象数量大致可计算时间),再根据期望的STW时间,可计算出本次gc可以回收多少个region。

收集器维护了一个优先回收的region列表, 实现了尽可能短的时候回收更多的region。

期望STW时间不能太低,否则每次gc回收不到足够的内存,会造成频繁gc,引发full gc

gc类型

Young GC, 当回收当前年轻代的时间远小于期望STW时间时, 会直接扩容年轻代,直到满足期望的STW值时,开始Young GC。

Mixed GC,当老年代的使用率达到-XX:InitiatingHeapOccupancyPercent时会触发,回收所有的年轻代、部分老年代和大对象区,若空间不足会触发full gc。

Full GC,暂停系统, 使用单线程进行回收,同serial,回收到足够的内存后,才开始mixed gc。

三色标记

,对象自身,下级引用,全部已经被遍历过了。

,自身与下级只遍历过一部分,没有完全遍历完。

,完全没遍历过

遍历结束后只会存在,黑白两色对象,白色对象没被遍历,说明不可达,可进行回收。

三色标记在并发阶段引发的问题及解决

并发阶段:用户线程和gc线程同时执行,用户线程执行的对象引用修改会影响到标记的准确性

多标,应该为白色,却标了黑色,不会被gc回收

在并发过程中产生的垃圾,如删除对象引用,或栈清空,由于黑色对象不会被访问,所以该批对象躲过了gc。

这些对象称为浮动垃圾

多标不会对系统造成影响,等待二次gc时回收即可。

漏标,应该为黑色,却标了白色,会被gc回收。

用户给黑色对象新引用了白色对象black.a = white,该白色对象是从某个灰色对象移过来的,还未被标记, 被黑色引用后,失去了被标记的机会。

漏标会造成误删除,必须解决

CMS: 写屏障-增量更新,在黑色对象引用新对象时(增量),将引用对象加入容器,等重新标记时,再次扫描。

G1:写屏障-原始快照SATB,在灰色对象置空引用对象时(删除),将置空的引用对象加入容器,等并发标记完后,再次扫描。

读写屏障

类似于aop思想, 在get set中,插入pre post方法

安全点

在代码中指定一些点,当线程运行到这些点的时候,状态是确定的,可以挂起线程,进行gc。

安全点位置:

方法返回之前

调用方法之后

抛出异常的位置

循环的末尾

安全区域

在一段代码中,引用关系不会发生变化,如sleep 中断等。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值