zoukankan      html  css  js  c++  java
  • JVM中对象的销毁

    1、可达性分析算法:

    可达性分析算法用来寻找将要销毁的对象,它的基本思路是:通过一系列的称为“GC ROOTs”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径成为引用链,当一个对象到GC ROOTs没有任何引用链想连时,则证明此对象是不可用的。如下图所示:

    对象 object5/object6/object7 虽然相互关联,但它们到GC Roots 是不可达的,所以它们会被判定为可回收的对象。

    在 Java 语言中,可作为GC Roots的对象包括下面几种:

      ·虚拟机栈(栈帧中的本地变量表)中引用的对象

      ·本地方法栈中 Native方法 引用的对象

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

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

    2、宣判对象死亡的过程:

    此过程以流程图的形式表示更为直观:

    F-Queue 队列的执行,是由一个虚拟机自动建立的、低优先级的 Finalizer 线程执行的。这里的执行是指虚拟机会触发这个方法,但不保证会等待方法执行结束,这样是为了防止 Finalizer 执行缓慢或发生死循环,进而引起 F-Queue 队列中其他对象永久等待,甚至整个内存回收系统崩溃。

    下面给出一段 finalize() 被执行但对象仍然存活的示例:

    /**
     * 此代码演示了两点:
     * 1.对象可以在被GC时自我拯救
     * 2.这种自救的机会只有一次。因为一个对象的 finalize()方法最多只会被系统自动调用一次
     * @author yangtf
     *
     */
    public class FinalizeEscapeGC {
        public static FinalizeEscapeGC SAVE_HOOK = null;
        
        public void isAlive(){
            System.out.println("Yes,I am still alive");
        }
        
        @Override
        protected void finalize() throws Throwable{
            super.finalize();
            System.out.println("finalize method executed!");
            FinalizeEscapeGC.SAVE_HOOK = this;    // 将自己赋值给 SAVE_HOOK
        }
        
        public static void main(String[] args) throws InterruptedException {
            SAVE_HOOK = new FinalizeEscapeGC();
            
            // 对象第一次成功拯救自己
            SAVE_HOOK = null;
            System.gc();
            
            // finalize方法优先级很低,所以暂停0.5秒以等待它
            Thread.sleep(500);
            if (SAVE_HOOK != null) {
                SAVE_HOOK.isAlive();
            } else {
                System.out.println("No, I am dead");
            }
            
            // 下面这段代码与上面完全相同,但这次自救失败了
            SAVE_HOOK = null;
            System.gc();
            
            Thread.sleep(500);
            if (SAVE_HOOK != null) {
                SAVE_HOOK.isAlive();
            } else {
                System.out.println("No, I am dead");
            }
        }
    }

    执行结果:

    finalize method executed!
    Yes,I am still alive
    No, I am dead

    从结果可以看出,SAVE_HOOK 对象的 finalize() 方法确实被GC收集器触发过,并且在被收集前成功逃脱了。

    执行第二次失败,因为任何一个对象的 finalize() 方法都只会被系统自动调用一次,如果对象面临下一次回收,它的 finalize() 方法不会被再次执行,因此第二段代码的自救失败。

    3、对象的引用

    JDK1.2后,Java 将对象引用概念进行扩张,将其分为:强引用、软引用、弱引用、虚引用,四种引用强度依次减弱。

    1)强引用:代码中普遍存在,类似“Object obj = new Object()”。只要强引用还存在,垃圾收集器永远不会对其引用的对象进行回收。

    2)软引用:用来描述还有用,但并非必须的对象。对软引用关联的对象第一次不回收,若第一次回收之后内存仍不够,则将其回收;即进行第二次回收。

    3)弱引用:比软引用更弱的引用。第一次垃圾回收就会将其回收。

    4)虚引用:也称为幽灵引用或幻影引用。一个对象是否有虚引用存在,完全不会对其生存时间构成影响,也无法通过虚引用来取得一个对象实例。为一个对象设置虚引用的唯一目的,就是能在这个对象被收集器回收时收到一个系统通知。

  • 相关阅读:
    转DataBinder.Eval总结
    ASP.NET环境下XML导出导入数据方法
    iOS开发中GCD在多线程方面的理解
    hdu 1678 优先队列
    hdu 1565 状态压缩DP
    hdu 1175 连连看
    hdu 1078 记忆化搜索
    hdu 1506
    hdu 1521 记忆化搜索
    三大博弈[转]
  • 原文地址:https://www.cnblogs.com/tf-Y/p/5272781.html
Copyright © 2011-2022 走看看