一篇就够,图文解析JVM 底层内存回收算法

       今天笔者讲讲JVM 的内存回收算法,大家都知道堆几乎放着所有对象的实例(当然其他小部分会基于逃逸分析存储在栈),并且在回收堆垃圾之前肯定会先判断堆里面哪些对象需要回收,哪些对象还存活着。大家应该多多少少听过“可达性分析算法”和“引用计数法”,接下来就详细介绍一下它们。

  • 引用计数法:说白了就是给对象加了一个引用计数器,哪个地方有使用到,计数器就会加一,当有引用的那个地方突然不引用了,计数器也会减一;而当计数器的值为0的时候,表示该对象不会再被引用。

      注意,这个算法逻辑很简单,但是目前主流的虚拟机并没有使用该算法来管理内存,理由很简单,有bug!没错,这个算法会出现问题,比如说,当两个对象互相引用的时候,双方的计数器值永远不会为0,这时候就算它们已经是属于垃圾对象了也会被回收的。

  • 可达性分析算法:将“GC Roots”作为起点,一直往下去深挖,只要有关联的对象就是存活对象,其余就是垃圾对象了。“GC Roots”正常指的是线程栈的本地变量、静态变量等等。

          尽管,已经筛选出了垃圾对象,但是JVM并不会直接就把它们回收,还需要再进一步判断它们有没有可能还存在着存活的对象。为什么这么做呢?Java的引用有强有弱,可分为四种:强引用(普通变量的引用)、软引用(将对象用SoftReference软引用类型的对象包裹)、弱引用(GC会直接回收)、虚引用(几乎不使用)。

          最后一步给垃圾对象宣判“死刑”的是通过finalize()方法,首先进行第一次的标记和筛选出哪些对象实现了finalize()方法,筛选条件是此对象是否有必要执行finalize()方法,而没有实现的可以直接回收内存;第二次标记的时候,看看那些垃圾对象是否在finalize()方法实现了“自救”,如果有的话就可以恢复为非垃圾对象,不会被回收;如果没有,就会被回收掉内存。这里也是垃圾对象唯一一次机会能够获得存活下去的机会,但是,由于运行代价极高,目前该方法官方不推荐使用。

         方法区主要回收的是无用的类,那么如何判断一个类是无用的类的呢?

           事实上,方法区判断一个类是无用类的条件是十分苛刻的。首先,必须保证该类没有任何被引用的实例;其次,它的类加载器已经被回收了;最后,对应的class对象没有在任何地方被引用,并且其他地方是没有办法通过反射来访问该类的任何方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值