总览
收集覆盖了finalize()的对象之后,将其添加到终结处理队列中,以在调用每个对象的finalize()方法之后进行清理。 如果您复活该物体,会发生什么?
何时定稿?
finalize方法由单线程系统任务调用,该任务针对已收集的每个对象调用此方法。 注意:终结队列中的节点是对象,概念上也具有finalize()方法。 对象完成后才能清理对象。
大多数对象(包括终结队列中的节点)不会覆盖finalize(),因此GC足够智能,可以检测到该事件,而不将其添加到队列中。 这些对象可以立即清除。 如果覆盖该方法,即使使用空方法,也会有所不同。
那复活的物体呢?
在finalize()方法中,您可以通过使对象指向某点来复活该对象。 例如静态集合。 GC不再可以收集该对象(直到再次丢弃),那么会发生什么呢?
该对象已被标记为已完成一次且不会重复完成。
static final List ZOMBIES = new ArrayList<>();static class Zombies {private int num;public Zombies(int num) {this.num = num;}@Overrideprotected void finalize() throws Throwable {System.out.println("Resurrect " + num);ZOMBIES.add(this);}@Overridepublic String toString() {return "Zombies{" + "num=" + num + '}';}}public static void main(String... args) throws InterruptedException {for (int i = 0; i < 3; i++)ZOMBIES.add(new Zombies(i));for (int j = 0; j < 5; j++) {System.out.println("Zombies: " + ZOMBIES);ZOMBIES.clear();System.gc();Thread.sleep(100);}}
版画
Zombies: [Zombies{num=0}, Zombies{num=1}, Zombies{num=2}]
Resurrect 2
Resurrect 1
Resurrect 0
Zombies: [Zombies{num=2}, Zombies{num=1}, Zombies{num=0}]
Zombies: []
Zombies: []
Zombies: []
在此示例中,僵尸一次添加到集合中,并通过finalize方法重新复活一次。 当第二次收集它们时,它们已标记为已完成并且不再排队。
结论
避免使用finalize()是个好主意,但要知道它仅在对象复活后才被调用,这是一个小小的安慰。
参考:来自Vantage Java博客的JCG合作伙伴 Peter Lawrey的Java Object resurrection 。
翻译自: https://www.javacodegeeks.com/2012/12/java-object-resurrection.html