前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java中一次对象的自我拯救探究

Java中一次对象的自我拯救探究

作者头像
明明如月学长
发布2021-08-27 16:13:09
3990
发布2021-08-27 16:13:09
举报

《深入理解java虚拟机》第二版 67页,一次对象自我拯救这个例子很不错,在这里分享出来。

并且从源码角度进行分析。

代码如下:

代码语言:javascript
复制
/**
 * 1 对象可以在被GC时自我拯救
 * 2 这种自救机会只有一次,因为一个对象的finalize()方法最多只会被系统自动调用一次
 * Created by 明明如月 on 2017-05-24.
 */
public class FinalizeEscapeGC {
    private static FinalizeEscapeGC SAVE_HOOK = null;
    private 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;
    }

    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();
        //因为finalize 方法优先级很低,所以暂停0.5秒等待它
        Thread.sleep(500);
        if(SAVE_HOOK != null){
            SAVE_HOOK.isAlive();
        }else{
            System.out.println("no, i am dead :(");
        }
    }
}

运行结果

Java中一次对象的自我拯救探究
Java中一次对象的自我拯救探究

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

我们先研究一下垃圾回收方法

Java中一次对象的自我拯救探究
Java中一次对象的自我拯救探究

此方法调用垃圾回收器,回收被遗弃的对象。并且和Runtime.getRuntime().gc()这个方法等价,因为从源码中我们看出其实就是直接调用了那个方法。

Java中一次对象的自我拯救探究
Java中一次对象的自我拯救探究

我们看到这个是原生的方法,哪怕gc方法没有被显式调用,虚拟机根据需要自动执行垃圾回收线程。

我们再看看Object对象的finalize()方法:

Java中一次对象的自我拯救探究
Java中一次对象的自我拯救探究
Java中一次对象的自我拯救探究
Java中一次对象的自我拯救探究

主要几点:

  1. 当垃圾回收器断定一个对象不再被引用,该对象的该方法就会被垃圾回收器调用。
  2. 子类可以重写finalize方法来释放系统资源或者执行一些清理的操作。
  3. finalize方法可以执行任何操作,包括再使得该对象可用(拯救该对象)。
  4. Java编程语言并不保证哪一个线程来调用某个对象的finalize方法。
  5. finalize方法只会被Java虚拟机调用一次。

主方法中,上半段和下半段代码相同,可是一次逃脱成功,一次逃脱失败,是因为任何一个对象的finalize()方法只会被系统自动调用一次,如果对象再次面临回收,他的finalize()方法不会再次被执行,第二段代码的自救行动就失败了(因为再次调用gc来执行垃圾回收,该对象的finalize方法不会再次被执行)。

书中作者不鼓励使用该方法来拯救对象。

作者表示有的教材鼓励采用这种方式在finalize()方法中“关闭外部资源”之类的工作。finalize()能做的工作通过try-finally或者其他方式也可以做得更好、更及时,所以请淡忘这个方法。

这一点和Java源码中的解释有点冲突,仅供参考,读者自己取舍就好。

大家在编程过程中,尤其在学习虚拟机的一些知识时,多去查看源码

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017-05-25 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档