深入理解JAVA虚拟机—第三章垃圾收集器和内存分配策略(二)对象的死亡

 2019-12-22 10:51  阅读(775)
文章分类:JVM
  • 上一篇说过了,目前主流的JVM使用的是可达性分析法,通过扫描JVM指定的某些对象作为根,扫描出整个内存中所有与之关联的对象,没有关联的对象则GC认为可以清理。

  • 但其实,在通过可达性分析法中不可达的对象,也并不是一定会被清除,当可达性分析后,会对没有被跟引用的对象进行第一次标记,并且执行一次筛选,筛选的条件就是对象是否有必要执行的finalize方法。对对象没有覆盖finalize方法或者finalize方法已经被虚拟机调用过。JVM会将这两种情况视为没有必要执行的finalize方法。

  • 如果这个对象被判定为必要执行时finlize方法时,那么这个对象会被设置到一个叫做F-Queue队列中,并在一个稍后由虚拟机自动创建的低优先级的Finlizer线程去执行它,执行其实是指JVM会去触发这个方法,并不会等待执行完毕,这样做是为了,如果一个对象的finalize方法执行缓慢,或者发生死循环,将会导致F-Queue一直处于等待状态,甚至导致整个内存回收系统崩溃

  • finlize方法是帮助对象逃脱死亡的最后一次机会,稍后GC会在F-Queue中对所有对象进行第二次小规模的标记,如果在finalize中拯救了自己(重新和引用链上的对象进行关联),例如将this赋值给某个对象的成员变量,那么第二次标记的时候,它将会被移除即将回收的集合;但是如果这个时候这个对象还没有逃脱的话,那么基本上等待它的就真的是死亡了。

    public class GcObj { public static GcObj SAVE_HOOK = null;

    @Override
    protected void finalize() throws Throwable {
    //第一次清理时虚拟机会执行这个方法,但是对于一个对象虚拟机只会执行一次这个方法
    super.finalize();
    System.out.println("清理方法运行了");
    SAVE_HOOK = this;
    }
    
    public void isAlive() {
    System.out.println("我还活着");
    }
    
    public static void main(String[] args) throws InterruptedException {
    SAVE_HOOK = new GcObj();
    //第一次拯救自己
    SAVE_HOOK = null;
    System.gc();
    Thread.sleep(500);
    if (SAVE_HOOK != null) {
    SAVE_HOOK.isAlive();
    } else {
    System.out.println("Dead");
    }
    System.out.println("第一次拯救结束");
    
    //第二次拯救自己 失败
    SAVE_HOOK = null;
    System.gc();
    Thread.sleep(500);
    if (SAVE_HOOK != null) {
    SAVE_HOOK.isAlive();
    } else {
    System.out.println("Dead");
    }
    }
    }
    
  • 这串代码中,首先GcObj对象通过重写了Object的finalize方法,这个方法中通过将This赋值给一个static对象,试图拯救自己17行到27行是第一次拯救的代码,执行GC后,因为SAVE_HOOK对象为null,那么创建的GcObj对象则会被GC标记,因为Finalizer线程优先级比较低,所以通过Sleep让main线程等待一下,之后再运行一次同样的代码,看如下的执行结果可知finalize确实被执行了一次,并且成功拯救了这个对象,第二次同样的操作缺无法拯救这个对象了

    清理方法运行了 我还活着 第一次拯救结束 Dead

  • 需要特别注意的是,之前很多人用finalize方法来视图调用关闭资源的方法,但是由于finalize方法运行代价高昂,需要多等待一次GC,不确定性大,无法保证调用顺序,这是不对的。如果需要关闭资源的话try finally代码块足够我们使用了。这个方法只需要知道存在以及什么时候调用即可,正常使用中不建议使用

点赞(0)
版权归原创作者所有,任何形式转载请联系作者; Java 技术驿站 >> 深入理解JAVA虚拟机—第三章垃圾收集器和内存分配策略(二)对象的死亡

相关推荐