现在,我写了一个简单的代码。
public class ToDo {
ToDo instance;
public ToDo () {
}
void foo() {
System.out.println("foo.");
}
void bar() {
System.out.println("bar.");
}
public static void main(String args[]) throws Throwable {
ToDo inDo = new ToDo();
inDo.foo();
inDo.finalize();
inDo.bar();
}
}
Object.java中的finalize是一个空函数,清理对象的繁重工作在哪里?
在对象被垃圾回收时调用Finalizer。这意味着它不应该调用'bar'如何仍然打印条。
答案 0 :(得分:3)
Object.java
中的最终结果是一个空函数,清理对象的繁重工作在哪里?
Java中的对象通常不会被“清理”。在C ++中,析构函数最常见的任务是释放已分配的内存,但在Java中,VM负责垃圾收集未使用的分配。终结器可用于释放非托管资源,例如本机OS UI组件,但您不能依赖它们来处理此作业,因为它们可能在对象停止使用后很长时间被调用,或者根本不会被调用。相反,您应该有一个方法,例如dispose()
或close()
(请参阅Closeable),您可以选择从终结器调用该方法作为一种安全网,但是您的客户端代码应该负责打电话。
当对象被垃圾收集时调用Finalizer。这意味着它不应该调用'bar'如何仍然打印条。
在终结器完成之前,对象仍然有效,因此调用bar
是可以接受的。如上所述,您可以使用终结器调用清理方法,以防客户端打开一些东西。
答案 1 :(得分:2)
您不应该自己致电finalize()
。如果它应该这样做,JVM会调用它。这种方法不会导致对象被GC化,而是进行清理,而且,这并不是普通凡人代码应该调用的东西。
答案 2 :(得分:1)
Object.java中的finalize是一个空函数,清理对象的繁重工作在哪里?
在JVM内部,作为垃圾收集器的一部分。您无权访问任何此逻辑。
当对象被垃圾收集时调用Finalizer。这意味着它不应该调用'bar'如何仍然打印条。
不完全是。在对象没有引用(因此准备好收集)和VM决定有效回收它的那一刻之间,但在有效地执行它之前的任何时刻都会调用finalize()
。这很重要,因为finalize()
不仅可以打印“bar”,而且甚至可以建立引用(通过执行AClass.aStaticField= this ;
,作为一个非常简单的示例),使对象或其他对象先前有资格再次收集“活着” ”。因此,在finalize()
之后再次检查对象的垃圾收集资格,并且可能中止收集。通过这样做,对象可以拒绝垃圾收集,但不是永远收集(见下文)。
有助于理解finalize()的其他想法?
finalize()
之间传递的时间段是如此可变,以至于通过close()
方法显式资源取消分配成为首选(“Javatic”?)方式和finalize()
使用已被劝阻。实际上,许多JVM在终止时不会调用任何finalize()
方法。finalize()
提出的挑战。如初。finalize()
不仅“恢复”自己的对象,而且还有其他对象的“复活”能力的后果尚未完全明确。 具有指定的是:“对于任何给定对象,Java虚拟机永远不会多次调用finalize方法。”。这意味着如果finalize()
“复活”其自己的对象,即使对象已准备好再次收集,也不会再次调用它。至少可以说非常奇怪的行为。实际上是随机的,如果两个对象以这种方式相互交错,因为Java在收集对象时不保证任何顺序。finalize()
。如果你这样做了,你将成为第一批依赖它的人之一。原则上,这个想法很好,但没有办法预测随着时间变得明显的后果。 为资源清理定义显式close()
方法。在某些情况下,监视资源使用情况的清理线程也很有用。 PS:Thread.suspend()
,Thread.resume()
,Thread.stop()
和Thread.destroy()
发生了类似情况。非常好的想法,在应用程序和JVM稳定性方面,练习证明是一个夜晚。唯一的区别是这些Thread
方法已被正式弃用,因为它们的影响(可辩解地)更大。
答案 3 :(得分:0)
当要收集对象时,垃圾收集器会调用
你调用finalize根本没有任何效果。 (这就像调用任何其他方法一样)。
答案 4 :(得分:0)
Object.java中的finalize是一个空函数,其中重要的是 清洁物体的工作是什么?
这是Object类中的一个空方法,但如果你要使用它的目的,那么你需要在你的类中重写它。
在对象收集垃圾之前,jvm会调用当对象被垃圾收集时调用Finalizer。这意味着它 不应该打电话给' bar'如何打印酒吧。
finalize方法。但作为一种简单的方法,您可以随时直接调用它。但是直接调用finalize并不会使对象准备好或收集垃圾。因此这样做:
inDo.finalize();
inDo.bar();
仍然有效,因为inDo
对象仍然被引用或激活而不是垃圾回收。
答案 5 :(得分:0)
如果您想查看完成工作,请运行此测试
公共类Test1 {
protected void finalize() {
System.out.println("finalize");
}
public static void main(String[] args) throws Exception {
new Test1();
System.gc();
}
}
请注意,System.gc不保证GC会运行,但它始终在我的HotSpot VM上运行。