[英]Messing with java finalize()
我读到JVM gc找到不可达的对象后,运行该对象的finalize()方法。 然后,它检查对象是否仍然无法访问,如果不是,则将其删除。 所以我写了一个finalize,它将再次使该对象的引用可用:
public class Stuff {
List<Object> list;
public Stuff(List<Object> list) {
this.list = list;
}
@Override
protected void finalize() throws Throwable {
list.add(this);
System.out.println("A Stuff is finalized");
}
}
这是主要方法:
public class Main {
public static void main(String[] args) {
List<Object> list = new ArrayList<>();
list.add(new Stuff(list));
list.remove(0);
System.gc();
System.out.println(list.get(0));
}
}
运行gc,因为在标准输出上显示“物料已最终确定”,但是随后main中的打印行抛出了IndexOutOfBoundsException。 我可以完全进行这项工作吗?
我通常根本不使用finalize,我只是想看看finalize是否可以使其对象的引用再次可用会很有趣。 我可以做这个工作吗?
终结器在专用终结器线程中运行,并且您编写的是线程不安全的代码。 例如,使用同步的集合。
另一个陷阱是,仅调用System.gc()
不能保证在方法调用返回时终结器已经运行。 终结器仅已排队在终结器线程的队列中(即使如此)。 要变通解决此问题,您实际上应该使用同步助手(例如CountDownLatch
并两次或三次调用System.gc()
以取得良好的效果。
在这里,您的代码通过以上思想得到了改进:
public class Stuff {
static final List<Stuff> list = Collections.synchronizedList(new ArrayList<Stuff>());
static final CountDownLatch cdl = new CountDownLatch(1);
@Override protected void finalize() {
list.add(this);
cdl.countDown();
}
public static void main(String[] args) throws Exception {
list.add(new Stuff());
list.remove(0);
System.gc();
System.gc();
cdl.await();
System.out.println(list.size());
}
}
List<Object> list = new ArrayList<>();
list.add(new Stuff(list));
list.remove(0);
System.gc();
System.out.println(list.get(0));
您正在创建的列表Object
“不是Lis
的实例牛逼Stuff
与实现类finalize
。 因此,预期ArrayIndexOutOfBound
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.