Java:不朽的对象和对象复活

什么是对象复活?

当没有其他对象引用该对象时,该Java对象可以进行垃圾回收。 当JVM:s垃圾收集器最终将要删除未使用的对象时,将调用该对象的finalize()方法。 但是,如果我们再次使用对象自己的finalize()方法重新创建对该对象的引用,则该对象可以复活。 在这种情况下,JVM将检测到再次引用了该对象,并避免将其删除。 隐喻地,该物体已经从死亡中复活了……

public class Immortal {

    private static final Set<Immortal> immortals = new HashSet<>();

    @Override
    protected void finalize() throws Throwable {
        System.out.println(Immortal.class.getSimpleName() + "::finalize for " + this);
        immortals.add(this); // Resurrect the object by creating a new reference 
    }

}

可以通过以下方式测试复活属性:

public class NewMain {

    public static void main(String[] args) {
        new Immortal();
        System.gc();
        sleep(1_000);
        System.gc();
        prompt("Press any key...");
    }

    private static void prompt(String msg) {
        try {
            System.out.println(msg);
            System.in.read();
        } catch (IOException io) {
        }
    }

    private static void sleep(long duration) {
        try {
            Thread.sleep(duration);
        } catch (InterruptedException ie) {
        }
    }

}

这将给出以下输出:

Immortal::finalize for com.blogspot.minborgsjavapot.resurected_object.Immortal@635cb856
Press any key...

通过检查Java堆,我们还可以看到尽管对象的终结器被调用,该对象仍然存在:

pemi$ jps
21735 NewMain
21736 Jps

pemi$ jmap -histo 21735 | grep Immortal
 164:             1             16  com.blogspot.minborgsjavapot.resurected_object.Immortal

终结器被调用了多少次?

如果以后取消引用了复活的对象,则该对象又有资格进行垃圾回收。 但是,这次
由于Java最多只能调用finalizer一次,因此不会再次调用finalize()方法。 我们可能还记得,不能保证终结器会被调用。 例如,如果程序由于任何原因终止,则仅放弃JVM中的对象,并且最终定形器将根本不会被调用,如在本示例中可以看到的:

public class NewMain2 {

    public static void main(String[] args) {
        new Immortal();
    }

}

当我们运行上述代码片段时,我们观察到从未调用Immortal::finalizer

对象复活好吗?

与使用finalize()方法一样,我们必须非常谨慎。 对我们Java开发人员的一般建议是根本不使用finalize() 。 此外,有人可能会说,复活一个对象与故意造成内存泄漏是一样的。

但是,有一些有趣的对象复活应用程序。 也许我们想对我们的对象进行事后分析,而又不更改使用该对象的实际应用程序。 通过使用对象复活,我们可以保存那些对象并在以后分析它们的内部状态,而与使用它们的应用程序无关。

翻译自: https://www.javacodegeeks.com/2016/03/java-immortal-objects-object-resurrection.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值