JVM系列:判断对象是否已死和四种垃圾回收算法总结-创新互联

判断对象是否已死

判断对象是否已死就是找出哪些对象是已经死掉的,以后不会再用到的,就像地上有废纸、饮料瓶和百元大钞,扫地前要先判断出地上废纸和饮料瓶是垃圾,百元大钞不是垃圾。判断对象是否已死有引用计数算法和可达性分析算法。

雁峰ssl适用于网站、小程序/APP、API接口等需要进行数据传输应用场景,ssl证书未来市场广阔!成为创新互联建站的ssl证书销售渠道,可以享受市场价格4-6折优惠!如果有意向欢迎电话联系或者加微信:028-86922220(备注:SSL证书合作)期待与您的合作!

1.引用计数算法

给每一个对象添加一个引用计数器,每当有一个地方引用它时,计数器值加 1;每当有一个地方不再引用它时,计数器值减 1,这样只要计数器的值不为 0,就说明还有地方引用它,它就不是无用的对象。如下图,对象 2 有 1 个引用,它的引用计数器值为 1,对象 1有两个地方引用,它的引用计数器值为 2 。

这种方法看起来非常简单,但目前许多主流的虚拟机都没有选用这种算法来管理内存,原因就是当某些对象之间互相引用时,无法判断出这些对象是否已死,如下图,对象 1 和对象 2 都没有被堆外的变量引用,而是被对方互相引用,这时他们虽然没有用处了,但是引用计数器的值仍然是 1,无法判断他们是死对象,垃圾回收器也就无法回收。

2.可达性分析算法

了解可达性分析算法之前先了解一个概念——GC Roots,垃圾收集的起点,可以作为 GC Roots 的有虚拟机栈中本地变量表中引用的对象、方法区中静态属性引用的对象、方法区中常量引用的对象、本地方法栈中 JNI(Native 方法)引用的对象。

当一个对象到 GC Roots 没有任何引用链相连(GC Roots 到这个对象不可达)时,就说明此对象是不可用的,是死对象。

如下图:object1、object2、object3、object4 和 GC Roots 之间有可达路径,这些对象不会被回收,但 object5、object6、object7 到 GC Roots 之间没有可达路径,这些对象就被判了死刑。

2.复制算法

把内存分为大小相等的两块,每次存储只用其中一块,当这一块用完了,就把存活的对象全部复制到另一块上,同时把使用过的这块内存空间全部清理掉,往复循环,如下图。

缺点:实际可使用的内存空间缩小为原来的一半,比较适合。

3.标记-整理算法

先对可用的对象进行标记,然后所有被标记的对象向一段移动,最后清除可用对象边界以外的内存,如下图。

4.分代收集算法

把堆内存分为新生代和老年代,新生代又分为 Eden 区、From Survivor 和 To Survivor。一般新生代中的对象基本上都是朝生夕灭的,每次只有少量对象存活,因此采用复制算法,只需要复制那些少量存活的对象就可以完成垃圾收集;老年代中的对象存活率较高,就采用标记-清除和标记-整理算法来进行回收。

在这些区域的垃圾回收大概有如下几种情况:

大多数情况下,新的对象都分配在Eden区,当 Eden 区没有空间进行分配时,将进行一次 Minor GC,清理 Eden 区中的无用对象。清理后,Eden 和 From Survivor 中的存活对象如果小于To Survivor 的可用空间则进入To Survivor,否则直接进入老年代);Eden 和 From Survivor 中还存活且能够进入 To Survivor 的对象年龄增加 1 岁(虚拟机为每个对象定义了一个年龄计数器,每执行一次 Minor GC 年龄加 1),当存活对象的年龄到达一定程度(默认 15 岁)后进入老年代,可以通过 -XX:MaxTenuringThreshold 来设置年龄的值。

当进行了 Minor GC 后,Eden 还不足以为新对象分配空间(那这个新对象肯定很大),新对象直接进入老年代。

占 To Survivor 空间一半以上且年龄相等的对象,大于等于该年龄的对象直接进入老年代,比如 Survivor 空间是 10M,有几个年龄为 4 的对象占用总空间已经超过 5M,则年龄大于等于 4 的对象都直接进入老年代,不需要等到 MaxTenuringThreshold 指定的岁数。

在进行 Minor GC 之前,会判断老年代大连续可用空间是否大于新生代所有对象总空间,如果大于,说明 Minor GC 是安全的,否则会判断是否允许担保失败,如果允许,判断老年代大连续可用空间是否大于历次晋升到老年代的对象的平均大小,如果大于,则执行 Minor GC,否则执行 Full GC。

当在 java 代码里直接调用 System.gc() 时,会建议 JVM 进行 Full GC,但一般情况下都会触发 Full GC,一般不建议使用,尽量让虚拟机自己管理 GC 的策略。

永久代(方法区)中用于存放类信息,jdk1.6 及之前的版本永久代中还存储常量、静态变量等,当永久代的空间不足时,也会触发 Full GC,如果经过 Full GC 还无法满足永久代存放新数据的需求,就会抛出永久代的内存溢出异常。

大对象(需要大量连续内存的对象)例如很长的数组,会直接进入老年代,如果老年代没有足够的连续大空间来存放,则会进行 Full GC。

最后

后续会持续更新性能优化专题知识,写的不好的地方也希望大牛能指点一下,大家觉得不错可以点个赞在关注下我,刚刚入驻,以后还会分享更多文章!

创新互联www.cdcxhl.cn,专业提供香港、美国云服务器,动态BGP最优骨干路由自动选择,持续稳定高效的网络助力业务部署。公司持有工信部办法的idc、isp许可证, 机房独有T级流量清洗系统配攻击溯源,准确进行流量调度,确保服务器高可用性。佳节活动现已开启,新人活动云服务器买多久送多久。


标题名称:JVM系列:判断对象是否已死和四种垃圾回收算法总结-创新互联
网页URL:http://pwwzsj.com/article/ccpesp.html