JVM垃圾收集器
2023-11-07 10:40:06 0 举报
AI智能生成
登录查看完整内容
JVM垃圾收集器、收集算法等
作者其他创作
大纲/内容
当前虚拟机的垃圾收集都采用分代收集
即将堆分为新生代和老年代,人后根据各个年代的特点选择合适的垃圾手机算法
分代收集理论
将内存分为大小相同的两份,每次使用其中一份,这一份内存使用完后,将GC过后还存活的对象复制到另一边,再清空内存
缺点:浪费内存,每一次都会有一半内存是空的无法使用
标记复制算法
标记存活对象后统一回收所有未被标记的对象(反之也行)
如果需要标记的对象太多,效率会不高
清除后会产生大量不连续的内存碎片
缺点
标记清除算法
标记存活对象,将所有存活对象像另一端移动,再清理末端边界以外的内存
解决了内存碎片问题
标记整理算法
垃圾收集算法
适合年轻代
适合老年代
之所以会有那么多垃圾收集器是目前还没有真正能够适应所有场景的收集器,一直在完善收集器
最基本,最古老的收集器,收集器的实现是单线程去完成的
只会有一条垃圾收集线程去执行垃圾回收,并且暂停其他工作线程知道回收结束
新生代(Serial)采用复制算法,老年代(Serial Old)采用标记整理算法
由于没有线程交互,在单线程机器上可以获得很高的单线程收集效率
在JDK5及以前的版本中使用
作为CMD收集器的后备方案
用途
年轻代使用
-XX:+UseSerialGC
老年代使用
-XX:+UseSerialOldGC
参数配置
Serial(串行收集器)
属于Serial收集器的多线程版本,将单线程实现垃圾回收改为多线程并发回收
修改线程数(不建议)
-XX:parallelGCThreads
垃圾回收线程数跟CPU核数相同
新生代(Parallel)采用复制算法,老年代(Parallel Old)采用标记整理算法(JDK8默认)
-XX:+UseParallelGC
-XX:+UseParallelOldGC
Parallel(并行收集器)
与Parallel收集器很类似,主要是可以配合CMD收集器一起使用
是许多运行在Server模式下的虚拟机的首选,除了Serial外可以和CMD一起使用的
-XX:+UseParNewGC
ParNew
以获取最短回收停顿时间为目标的收集器,注重用户体验
是HotSpot第一款真正意义上的并发收集器,实现了垃圾收集线程与其他线程(基本上)同时工作
属于一种标记清除算法实现
暂停其他线程(STW),并记录GC ROOT直接能引用的对象,速度很快
初始标记
从GC ROOT直接引用对象开始遍历整个对象图,耗时较长,但是不STW,GC线程与应用线程并发执行
标记完的时候,已经标记过的对象可能状态已经发生改变
并发标记
为了修正并发标记期间,由于应用线程还在执行导致对象状态发生变动的这部分标记记录
标记也会暂停其他线程,且停顿时间会比初始标记稍长
主要用三色标记里面的增量更新算法做重新标记
重新标记
开启应用线程,同时GC线程开始清空未标记的区域
如果有新增对象会进行标记,不做任何处理(三色标记)
并发清理
重置本次GC过程中的标记数据
并发重置
实现:
采用并发收集,停顿时间少
优点
对CPU资源敏感,会和服务抢资源
并发标记和并发清理阶段又产生的垃圾(只能等下一次GC)
无法处理浮动垃圾
使用的回收算法会有大量空间碎片产生
上一次垃圾回收还没执行完,然后又触发Full GC
即有可能上一次GC还在并发标记或者并发清理阶段,应用线程来了大对象又造成GC
concurrent mode failure,会STw,然后用Serial Old进行垃圾回收
执行过程中的不确定性
优缺点
使用CMS垃圾收集器
-XX:+UseConcMarkSweepGC
并发的GC线程数
-XX:ConcGCThreads
FullGC之后做压缩整理(减少碎片)
-XX:UseCmsCompactAtFullCollection
进行多少次GC后整理,默认0
-XX:CMSFullGCBeforeCompaction
设置老年代触发GC的阈值,默认92%
-XX:CMSInitiatingOccupancyFraction
只使用设定的GC阈值,否则JVM仅在第一次设定改值,后序会自动调整大小
-XX:+UseCMSInitiatingOccupancyOnly
在CMS GC启动前启动一次minorGC,减少老年代会年轻代的引用,降低标记时间
-XX:+CMSScavengeBeforeRemark
初始标记的时候使用多线程去执行
-XX:+CMSParallelInitialMarkEnabled
重新标记的时候使用多线程去执行
-XX:+CMSParallelRemarkEnabled
核心参数
CMS(Concurrent Mark Sweep)
是一款面向服务器的垃圾收集器,主要对配置多核处理器及大容量内存的机器,以极高概率满足GC停顿时间要求的同时还具备高吞吐量
保留了年轻代和老年代的概念,但是不再进行物理隔阂
将java堆分为多个大小相等的独立区域(Region),JVM目标是不超过2048个Region,实际使用可以超过,但是不推荐
Region大小一般为堆内存除以2048,也可手动指定(不推荐)
概念
占堆内存5%
在运行过程中会不停增加Region
最高占比不会超过60%(默认),也可手动调整
Eden与Survivor的占比还是8:1:1
年轻代
存储到达指定年龄的对象
老年代(Old)
专门存放短期巨型对象,不用直接进老年代
存储占用内存超过了一个Region大小50%的对象
好处:节约老年代的空间,避免因为老年代空间不够的GC开销
大对象(Humongous)
一个Region可能之前是年轻代,如果Region进行了垃圾回收,之后可能又会变成老年代
分代存储
内存划分原理
远远小于则增加年轻代的Region,继续给新对象存放,再次计算
接近设定值,触发YoungGC
会先计算Eden区回收需要的时间是否接近用户设定值
YoungGC
老年代堆占有率达到设定值触发
回收所有的Young和部分Old(根据期望的GC停顿时间确定old区垃圾收集的优先顺序)以及大对象区
需要把各个region中存活的对象拷贝到别的region里去,拷贝过程中如果发现没有足够的空region能够承载拷贝对象就会触发一次Full GC
MixedGC(主要)
停止应用线程,采用单线程进行标记、清除和压缩整理出Region供下一次MixedGC使用
非常耗时
FullGC
收集器分类
暂停所有其他线程,记录GC ROOT直接引用的对象(速度很快)
初始标记(STW)
与CMS的并发标记一致
与CMS重新标记一致
最终标记(STW)
先计算各Region的回收价值和成本排序,根据用户所期待的GC停顿STW(G1基本围绕这个STW时间实现)时间来制定回收计划
在后台维护了一个优先列表,优先选择回收价值最大的Region
筛选
回收算法主要用的是复制算法,将一个Region中存活的对象复制到另一个Region中,几乎不会有太多碎片
STW期望时间是用户控制的,只能回收一部分Region
停顿其他线程可以大幅提高收集效率
注意:CMS回收阶段是跟用户线程一起并发执行的,G1因为内部实现太复杂暂时没实现并发回收,不过到了ZGC,Shenandoah就实现了并发收集,Shenandoah可以看成是G1的升级版本
STW执行的原因
筛选回收(STW)
MixedGC 执行流程
50%以上的堆被存活对象占用
对象分配和晋升的速度变化非常大
垃圾回收时间特别长,超过1秒
8GB以上的堆内存(建议值)
停顿时间是500ms以内
适用场景
优化建议
G1(Garbage First)
ZGC(The Z Garbage Collector)
垃圾收集器
关注吞吐量(CPU的利用率)
关注用户停顿时间(STW),提高用户体验
按照“是否访问过”为条件进行访问对象颜色标记
现代追踪式(可达性分析)的垃圾回收器几乎都借鉴了三色标记的算法思想,尽管实现的方式不尽相同:比如白色/黑色集合一般都不会出现(但是有其他体现颜色的地方)、灰色集合可以通过栈/队列/缓存日志等方式进行实现、遍历方式可以是广度/深度遍历等等
表示对象已经被垃圾收集器访问过,且这个对象的所有引用都已经扫描过,且是安全存活的
如果有其他对象引用指向黑色对象,无需重新扫描
黑色对象不可以直接(不经过灰色)指向某个白色对象
黑色
表示对象已经被垃圾回收器访问过,但对象上至少存在一个引用还没有被扫描过
灰色
表示对象尚未被垃圾回收器扫描过
可达性分析刚刚开始阶段,所有对象都是白色的
如果扫描结束仍然还是白色,即代表不可达
白色
三色解释
在标记过程中,由于部分局部变量(GC ROOT)被销毁,而刚有这个引用又被扫描过且标记为非垃圾对象,这部分本来应该是要被回收的确又没有进行回收
并发标记(并发清理)开始后产生的新对象,通常做法是直接全部变成黑色,不进行清除,但是期间也可能会变成可回收对象
起因
浮动垃圾不会影响垃圾回收正确性,只是需要下一轮GC才会回收
多标引起浮动垃圾
漏标会导致被引用的对象被当成垃圾对象回收,这属于严重BUG
增量更新
原始快照(SATB)
解决方案
漏标
问题
给某个对象的成员变量赋值前后,加一些处理
正常赋值
写屏障实现SATB,当对象A的成员变量的引用发生变化时,比如新增引用(a.d = d),我们可以利用写屏障,将A新的成员变量引用对象D记录下来:
写屏障赋值
写屏障
在获取对象属性前后,加一些处理
读取成员变量是记录读取到的对象
读屏障读取成员信息
读屏障
读写屏障
写屏障+增量更新
CMS
写屏障+SATB
G1
ZGC
各类收集器处理并发标记漏标处理方案
为什么G1用SATB,CMS用增量更新?
三色标记算法(并发标记过程)
可达性扫描跨代问题
JVM垃圾回收实现
0 条评论
回复 删除
下一页