GC的4种算法
复制算法
我们先来看一张原理图
明确发生的作用域
年轻代中采用的
Minor GC
这种GC算法采用的复制算法
过程分析
当GC开始后 对象只会存在于Eden和From区 而To区是空的 紧接着进行GC Eden中所有存活的对象和From中没有到阈值的对象被复制到To区 这个时候Eden和From区的对象已经被清空了 这个时候From和To区会交换他们的角色 也就是新的To就是上次的From 新的From就是上次的To区 这样的目的始终
保证To区是空的
Minor GC会一直进行这样的过程 直到To区被填满 会将所有对象移动到老年代
上图形象理解
Eden中的红色代表Eden中的存活对象 From区中的红色代表From区中的存活对象 复制就是把Eden中的红色对象和From中的红色对象拿到To去中 然后谁空谁是To 完成了To和From的角色交换 始终保持To区是空的
抽象出一个转移过程
一旦发生GC 就是将10%的from和80%的eden中存活的对象转移到to去当中 接下来将90%除to区之外的空间全部释放
劣势
适用于存活率不高的情况 如果存活率很高 我们就要把所有的对象都复制一遍
浪费了内存
需要维护对象间的region的引用关系
标记清除
同样我们先看原理图
明确发生的作用域
标记清除算法发生在老年代
思想
先将有效指引的对象标记,再清除未标记的对象
优点
相比复制算法来说不浪费内存
缺点
效率低(因为要遍历扫描2次),会产生内存碎片(清除后的内存是不连续的)
标记整理(压缩)
为了解决Copying算法的缺陷,充分利用内存空间,提出了Mark-Compact算法。该算法标记阶段和Mark-Sweep一样,但是在完成标记之后,它不是直接清理可回收对象,而是将存活对象都向一端移动,然后清理掉端边界以外的内存。
- 位置:发生在JVM虚拟机的老年代中
- 思想:将标记的对象连续的放到一端,将未标记的对象放到另一端,然后将未标记的对象清除
- 优点:与标记清除算法比,内存是连续的,与复制算法比不浪费内存
- 缺点:效率比复制算法低,需要多维持一个链表,用于使幸存的对象连续
引用计数法
给对象添加一个引用计数器,当有一个地方引用它时,计数器值就加1;当引用失效时,计数器就减1;任何时候计数器都为0的对象就是不可能再被使用的
小总结
-
分代收集算法
一般是把Java堆分为新生代和老年代,这样就可以根据各个年代的特点采用最适当的收集算法。在新生代中,每次垃圾收集时都发现有大批对象死去,只有少量存活,那就选用复制算法,只需要付出少量存活对象的复制成本就可以完成收集。而老年代中因为对象存活率高、没有额外空间对它进行分配担保,就必须使用“标记-清理”或“标记-整理”算法来进行回收。
本文参考:https://blog.csdn.net/weixin_41047933/article/details/86009018