JVM垃圾收集器

本文详细介绍了Java垃圾收集器的不同类型,包括Serial、ParNew、ParallelScavenge、CMS、SerialOld和ParallelOld。讲解了它们的特点、工作原理和优化目标,特别强调了并发标记清理和暂停时间目标。还重点分析了G1收集器的特性,如分区、并发收集、SATB算法以及如何减少Full GC的影响。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

说起垃圾收集器,咱们先画个图
在这里插入图片描述

YOUNG 年轻代

Serial

特点:
    Serial收集器是HotSpot运行在client模式下的默认新生代收集器,它的特点是只用一个cpu,一个线程去完成GC工作,且在进行垃圾收集时必须暂停其他所有的工作线程(STW)
年轻代串行回收

ParNew

特点:
		服务器多核的情况下效率要比Serial要高,但是并不能解决STW,单核服务器效率和Serial效率差不多
		ParNew收集器是Serial的多线程版本,包括控制参数、收集算法、STW、对象分配规则、回收策略等都与Serial完全一样,(VM启动CMS收集器的默认新生代收集器)
年轻代 配合CMS的并行回收
Parallel Scavenge
特点:
		与ParNew类似,Parallel Scavenge也是使用复制算法,也是并行多线程收集器,但与其他收集器关注尽可能缩短垃圾收集时间,Parallel Scavenge更关注系统吞吐量;
		系统吞吐量 = 运行用户代码时间/(运行用户代码时间+垃圾收集时间)
年轻代并行回收

OLD

CMS

concurrentMarkSweep老年代并发垃圾回收器:垃圾回收和应用程序同时运行,降低STW的时间(200ms)CMS的问题问题比较多,所以现在没有一个版本默认时CMS,只能手工指定
CMS既然是MarkSweep,就一定会有碎片化的问题,碎片达到一定程度,CMS的老年代分配对象分配不下的时候,使用Serial Old 进行老年代回收

phases 执行过程
	1、initial mark
			初始标记,标记出根对象
			这个过程会触发STW,由于是根对象,所以比较少,STW时间会很短
	2、concurrent mark
			并发标标记
			耗时最长,是和工作线程同时,不会触发STW
			这个过程会产生另一个问题,有可能在标记的过程中,对象不是垃圾对象了
	3、remark
			重新标记
			对并发标记的过程中,被修改过的对象重新标记
			标记的对象个数较少,会触发STW,耗时较短
	4、concurrent sweep
			并发清理,会启动多个线程进行清理
算法:
	CMS使用 三色标记 + Incremental Update
			1、当一个白色对象被一个黑色对象引用
			2、将黑色对象重新标记为灰色,让collector重新扫描

Serial Old

特点:
		和新生代的Serial收集器差不多,新生代中使用的算法是mark-sweep(标记-清除)算法,而老年代中使用					的是标记-整理算法
		此算法有一个致命的缺点,单线程清理
		
单线程串行化收集器
Parallel Old
特点:
		老年代的垃圾回收,但与Parallel Scavenge不同的是,它使用的是Mark-Compact(标记整理)
		注重于吞吐量及CPU资源敏感的场合
		
				
​``````properties
G1
G1的分代区域不是固定的,如eden区经过垃圾回收后有可能是old区
region 分区
	1、eden
	2、survivor
	3、old
	4、humongous 大对象 (超过region区的50%为大对象)
特点
	1、并发收集
	2、压缩空闲空间不会延长GC的暂停时间
	3、更易预测的GC暂停时间
	4、使用不需要实现很高的吞吐量的场景,高响应

尽量保持不要FullGC,因为jdk10之前FullGC是单线程进行的

软件架构中两种重要的思想
	1、分而治之
	2、分层
1、collection set = Cset
	存储需要被回收的垃圾集合
			垃圾收集器不需要扫描整个堆,找到cset直接回收即可
2、RememberedSet = RSet(hashset)
	记录了其他Region中的对象到本Region的引用
			垃圾收集器不需要扫描整个堆找到谁引用了当前分区中的对象,只需要扫描RSet即可;
Card Table
	由于做YGC时,需要扫描整个Old区,效率非常低,所以JVM设计了CardTable,如果一个Old区
	CardTable中有对象指向Y区,就将它设为Dirty,下次扫描时,只需要扫描Dirty Card在结构上,Card table用BitMap实现
新老年代比例
	5%~60%
	不需要手动指定,G1会按照实际情况动态调整
GC触发时机:
	YGC 
		eden空间不足
		多线程并行执行
	FGC
		Old空间不足
		System.gc()
算法:
	使用三色标记+SATB
		白色:未被标记的对象
		灰色:自身被标记,成员变量未被标记
		黑色:自身和成员变量已标记完成
  漏标:B-C消失,A-D建立
		打破漏标
			1、incremental update 增量更新(CMS使用此算法)
					关注引用的增加,把黑色重新标记为灰色,下次重新扫描属性
			2、SATB snapshot at the beginning 关注引用的删除(G1)
          在起始的时候做一个快照
          当B->D消失时,要把这个引用推到GC的堆栈,保证D还能被GC扫描到
          为什么G1要使用SATB
          	灰色到白色引用消失时,如果没有黑色指向白引用会被push到堆栈
          	下次扫描时拿到这个引用,由于有RSet的存在,不需要扫描整个堆区查找指向白色的引用,
          	效率比较高,SATB配合RSet浑然天成
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值