java 对象复活
总览
收集覆盖了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;
}
@Override
protected void finalize() throws Throwable {
System.out.println("Resurrect " + num);
ZOMBIES.add(this);
}
@Override
public 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
java 对象复活