开启生长之旅!这是我参与「日新计划 12 月更文挑战」的第28天,点击检查活动概况
上篇文章浅显易懂JVM(十一)之怎么判别目标“已死”现已浅显易懂的解析JVM是怎么评判目标不再运用,不再运用的目标将变成“废物”,等待收回
废物收回算法有多种,适用于不同的场景,不同的废物搜集器运用不同的算法
本篇文章将环绕废物收回算法,浅显易懂的解析废物收回分类以及各种废物收回算法
废物收回算法
废物收回分类
废物搜集器有着多种GC方法,不同的GC方法有自己的特点,收回的堆内存部分也不同
堆内存分为新生代和老时代,新生代存储“年青”的目标,老时代存储“老”或内存大的目标,目标年纪由阅历多少次GC来判别
其间整堆搜集时不只会收回整个堆还会收回元空间(直接内存)
-
部分搜集(Partial GC): 搜集目标是部分空间
- 新生代搜集(Minor GC/ Young GC):搜集新生代Eden、Survive to、Survive from区
- 老时代搜集(MajorGC/Old GC):搜集老时代
- 混合搜集(Mixed GC):搜集整个新生代和部分老时代
-
整堆搜集(Full GC): 整个堆 + 元空间
符号-铲除算法
Mark-Sweep
符号:从GCRoots开始遍历引证链,符号一切可达目标 (在目标头中符号)
铲除:从堆内存开始线性遍历,发现某个目标没被符号时对它进行收回
符号-铲除算法完成简略、不需求改动引证地址,可是需求两次遍历扫描功率不高,而且会呈现内存碎片
留意:这儿的铲除并不是真正意义上的收回内存,只是更新闲暇列表(符号这块内存地址为闲暇,后续有新目标需求运用就掩盖)
仿制算法
Copying
Survive区分为两块容量相同的Survive to区和Survive from区
每次GC将Eden区和Survive from区存活的目标放入Survive to区,此刻Survive to区改名为Survive from区,本来的Survive from区改名为Survive to区 确保Survive to区总是闲暇的
假如Survive from区的目标通过必定次数的GC后(默许15次),把它放入老时代
流程图
留意:图中的dean为Eden区(写错)
留意:最终的survive from区存活目标占用的内存应该是(那两块蓝色)挨着一起的,图中为了标识字分开来了
仿制算法不需求遍历,而且不会产生内存碎片,可是会浪费survive区一半的内存,移动目标时需求STW暂停用户线程,而且仿制后会改动引证地址(hotspot运用直接指针访问,还要改动栈中reference履行新引证地址)
假如仿制算法中目标存活率太高会导致十分消耗资源,因此一般只要新生代才运用仿制算法
符号-收拾算法
Mark-Compact
符号:从GCRoots开始遍历引证链,符号一切可达目标(在目标头中符号) (与符号-铲除算法共同)
收拾:让一切存活目标往内存空间一端移动,然后直接纳拾掉边界以外的一切内存
符号-收拾算法不会呈现内存碎片也不会浪费空间,可是功率低(比符号-铲除还多了收拾功用),移动目标导致STW和改动reference指向
假如不移动目标会产生内存碎片,内存碎片过多,将无法为大目标分配内存
还有种方法:屡次符号-铲除,等内存碎片多了再进行符号-收拾
分代搜集算法
符号铲除mark-sweep | 仿制copying | 符号收拾mark-compact | |
---|---|---|---|
速度 | 中 | 快 | 慢 |
GC后是否需求移动目标 | 不移动目标 | 移动目标 | 移动目标 |
GC后是否存在内存碎片 | 存在内存碎片 | 不存在内存碎片 | 不存在内存碎片 |
需求移动目标 意味着 要改动改目标引证地址 也就是说要改动栈中reference
指向改目标的引证地址,而且会产生STW中止用户线程
当空间中存在很多内存碎片时,可能导致大目标无法存储
分代搜集算法 : 对待不同生命周期的目标能够选用不同的收回算法(不同场景选用不同算法)
年青代: 目标生命周期短、存活率低、收回频频,选用仿制算法,高效
老时代: 目标生命周期长、存活率高、收回没年青代频频,选用符号-铲除 或混用 符号-收拾
增量搜集算法
mark-sweep、copying、mark-compact算法都存在STW,假如废物收回时刻很长,会严重影响用户线程的呼应
增量搜集算法: 选用用户线程与废物搜集线程替换履行
增量搜集算法能够提高用户线程的呼应时刻,但存在GC、用户线程切换的开销,下降了吞吐量,GC成本变大
分区算法
堆空间越大,GC时刻就会越长,用户线程呼应就越慢
分区算法: 将堆空间划分为接连不同的区,依据要求的中止时刻合理收回n个区,而不是一下收回整个堆
每个区独立运用,独立收回,依据能承受的中止时刻控制一次收回多少个区
G1搜集器以及两块低延迟搜集器Shenandoah、ZGC就运用到这种分区算法
总结
本篇文章环绕废物收回算法,浅显易懂解析废物收回分类、符号铲除、仿制、符号收拾、分代搜集、增量搜集、分区算法等多种算法
从废物收回空间上划分能够分为Full GC收回整个堆加上元空间、Minor GC收回新生代、major GC收回老时代、mixed GC收回新生代加老时代
符号铲除算法会遍历引证链符号可达目标从而收拾不可达目标,会产生内存碎片,速度一般
仿制算法不会产生内存碎片,而且速度很快,可是会浪费survivor区一半空间,而且会移动目标
符号收拾算法在符号收拾基础上添加收拾功用,不会产生内存碎片,但会移动目标,速度慢
不同的算法有不同的特点,应对新生代能够运用仿制算法,应对老时代能够运用标签铲除/收拾算法
增量搜集运用GC、用户线程替换履行,尽管下降用户呼应,但线程切换、吞吐量下降会添加GC成本
分区算法将堆内存划分为多个区,依据能够接纳的中止时刻来收回性价比高的多个区,中止时刻既在能够接纳时刻内,又能够收回性能比高的区
最后
-
参考资料
- 《深化了解Java虚拟机》
本篇文章将被收入JVM专栏,觉得不错感兴趣的同学能够保藏专栏哟~
觉得菜菜写的不错,能够点赞、关注支撑哟~
有什么问题能够在评论区交流喔~