BYTECODES

Java对象已死

如何判断java对象已经不再使用

引用计数法

引用计数法是在对象中使用一个字段跟踪该对象被使用的次数,当次数为0时,表示对象不再被使用,可以回收

优点:原理简单,判定效率高

缺点:无法解决循环引用问题,即两个对象互相引用,但其实这两个对象已经没有被使用。

可达性分析

从根对象(GC Roots)开始查找所引用的对象,没有被引用到的即是不再被使用的对象,可以回收。可以做根对象有:

. 虚拟机栈中引用的对象

. 方法区中静态属性引用的对象

. 方法区中常量引用的对象

. 本地方法栈中引用的对象

. Java虚拟机内部的引用,比如系统类加载器

. 所有被同步锁持有的对象

. 反映Java虚拟机内部情况的JM XBean、JVM TI中注册的回调、本地代码缓存等

除了这些固定的GC Roots,垃圾回收器还会根据回收的空间类型和大小把其他一些对象加入到GC Roots中。

再谈引用

Java 1.2版后,引用分为强引用,软引用,弱引用及虚引用

强引用:Java中最普遍的引用关系,比如Object o = new Object,是最强的一种引用

软引用:SoftReference,用来描述一些对象还有用,但非必须的对象。被软引用引用的对象,在内存溢出之前,进行二次回收。回收后内存还不足,才会抛出异常。

弱引用:比软引用还要弱一些,被弱引用引用的对象只能存活到下一次垃圾回收。

虚引用:是最弱的一种引用关系,无法通过虚引用来获取一个对象,为一个对象设置虚引用的唯一目的是在回收时可以收到一个系统通知。

生存还是死亡

即使在不可达分析中,对象被判定为不可达,但也不是一定会被垃圾回收的,这里会做一次标记。接下来进行一次筛选,判断对象是否需要做finalize()操作,如果需要执行,则会放入F-queue队列中,等待虚拟机的低调度优先级的Finalizer线程去执行。随后,收集器会对F-queue队列再做一次标记,没有在finalize中成功逃脱的对象,就会被垃圾回收。

方法区中的垃圾回收

主要回收不再使用的常量及类型信息。

判断一个类型不再使用:

  1. 没有与此类型相关联的实例

  2. 类的加载器已经被回收

  3. 该类对应的java.lang.Class对象没有在任何地方使用,无法通过反射生成类实例

    Java虚拟机被允许对满足上述三个条件的无用类进行回收,这里仅是“允许”。