JVM基础 -> JVM有哪些垃圾回收算法?
JVM有哪些垃圾回收算法?
- 可达性分析法
- 标记清除算法
- 拷⻉算法
- 标记压缩算法
- 分代收集算法
垃圾回收会经历两个阶段: 标记可回收对象阶段 -> 可达性分析法 垃圾清除阶段 -> 标记-清除算法 标记-拷⻉算法 标记-压缩算法 分代收集算法
标记可回收对象阶段
-
标记可回收对象阶段使用的算法是可达性分析法 可达性分析法: 从 GC Roots 开始向下搜索,搜索所⾛过的路径称为引⽤链。当⼀个对象到 GC Roots 没有任何引⽤链相连时,则证明此对象是不可⽤的,那么虚拟机就判断是可回收对象。 可达性分析法是垃圾回收算法的前提,是非常重要的 因为垃圾回收算法主要考察的是清除垃圾阶段时使用的算法 所以可达性分析法可以查看我都这篇博客
垃圾清除阶段
这个阶段有多个算法,会在不同的情况下选择合适的算法执行 ,这个怎么去选择合适的算法叫分代收集算法
我们会将分代收集算法放到最后去讲,它集合了所有垃圾回收算法
虚拟机都是使用这个分代收集算法的
MarkSweep 标记-清除算法:他是最先出现的垃圾回收算法,有着一些考虑不周的情况,存在一些bug
-
算法在标记阶段使用可达性分析法 这种算法是很简单的逻辑,就是把经过可达性分析法之后,已经确定为垃圾的对象都删除。 他是最先出现的垃圾回收算法,有着一些考虑不周的情况,存在一些bug 会产⽣⼤量的内存碎⽚,清除之后内存会很散乱 所以有必要其他算法来修复这个bug 如下图
Copying 标记-复制算法:为了解决标记清除算法的内存碎⽚问题,产⽣了拷⻉算法,JVM的新生代都用的拷⻉算法。
-
算法在标记阶段使用可达性分析法 拷⻉算法将内存分为⼤⼩相等的两半,每次只使⽤其中⼀半。 垃圾回收时,将当前这⼀块的存活对象全部复制到另⼀半,然后当前这⼀半内存就可以直接清除。 这种算法没有内存碎⽚,但是他的问题就在于浪费空间。 ⽽且,他的效率跟存货对象的个数有关。 如下图
MarkCompack 标记-整理算法:为了解决标记-复制算法的缺陷,就提出了标记-整理算法,JVM在老年代默认都是标记-整理算法。
-
算法在标记阶段使用可达性分析法 在完成标记之后,不是直接清理垃圾内存 ⽽是将存活对象往⼀端移动,然后将端边界以外的所有内存直接清除。 如下图
分代收集算法 -> 我们的重点
分代收集算法: 这个算法并没有新的内容,只是根据对象的存活的时间的长短,将内存分为了新生代和老年代,这样就可以针对不同的区域,采取合适的算法。
-
新生代,每次都有大量对象死亡,有老年代作为内存担保,采取标记-复制算法。 新生代的Eden区经过垃圾回收一次后,还存活的对象会被转移到s区 新生代s区中,s0,s1这两个区域,内存都是相同大小 s区经过垃圾回收,对象在s0,s1区域又来回复制倒腾 为什么说有老年代作为内存担保? 因为当新生代来回复制对象,内存超了的时候,要么自适应调整新生代内存,要么直接进入老年代 老年代,对象存活时间长,采用标记-整理,或者标记-清除算法都可。 具体使用哪种算法是需要判断老年代用的哪种垃圾回收器来决定的 CMS垃圾回收器 : 主要标记清除算法 其他垃圾回收器: 标记整理算法 当垃圾达到阈值(空间担保值),一定以及必定会触发FullGC FullGC 不管你是什么回收器,他是垃圾回收的最后尊严,成败在此一举 无论如何怎么整理,怎么垃圾回收,内存都不够了,就说明必须要进行JVM调优了 单纯的垃圾回收已经不顶用了
下一篇:
Java基础补充--面向对象编程初级部分