我需要知道在JVM
中何时调用finalize()
方法。我创建了一个测试类,通过覆盖finalize()
方法将其写入文件,但它未被执行。有人可以告诉我为什么它没有被执行吗?
我需要知道在JVM
中何时调用finalize()
方法。我创建了一个测试类,通过覆盖finalize()
方法将其写入文件,但它未被执行。有人可以告诉我为什么它没有被执行吗?
finalize 方法不能保证一定会被调用。该方法在对象变得可回收时被调用。有许多情况下,对象可能不会被垃圾回收。
GC.KeepAlive()
函数,它除了强制GC假定可能使用对象外什么也不做,但我不知道Java中是否有这样的函数。可以使用volatile
变量来实现这个目的,但仅出于这个目的使用变量似乎是浪费的。 - supercatFinalizerReference
加入队列可能更有益,这样就不需要GC循环来发现没有引用。同步足以确保* happens-before *关系;由于finalization可能(实际上是)在不同的线程中运行,因此通常形式上仍然是必要的。Java 9将添加Reference.reachabilityFence
… - HolgerFinalize
。对于只希望在单个线程中使用的对象,是否通常期望同步代码?如果一个对象执行一些需要在放弃之前撤消的操作(例如打开套接字连接并获取对端资源的独占使用权),那么在代码仍在使用套接字时,使用终结器关闭连接将是一场灾难。代码是否使用同步是正常的... - supercatfinalize()
时使用线程安全的构造是强制性的。但是当您仅依靠不可变性来实现线程安全时,缺乏显式对象使用确实可能是灾难性的。这是一个真正的问题。这就是为什么使用引用API更可取的原因;在那里,您可以完全控制何时以及在哪个线程中轮询ReferenceQueue
以清理资源。 - Holger根据在openjdk 18上发布的JEPS 421,finalize()
方法的功能将被标记为deprecated(forRemoval=true)
,这意味着在jdk 18之后的某个版本中将永久删除该方法。
从jdk 18开始,新的命令行选项--finalization=disabled
将在所有地方禁用终结机制,甚至包括jdk本身内部的声明。
这也与此处的问题相关,因为它计划删除的原因是它包含一些主要缺陷。其中一个缺陷是对象变得不可达和其终结器被调用之间可能会经过很长时间。同时,GC不能保证任何终结器都会被调用。
覆盖 finalize 方法的类
public class TestClass {
public TestClass() {
System.out.println("constructor");
}
public void display() {
System.out.println("display");
}
@Override
public void finalize() {
System.out.println("destructor");
}
}
finalize方法被调用的几率
public class TestGarbageCollection {
public static void main(String[] args) {
while (true) {
TestClass s = new TestClass();
s.display();
System.gc();
}
}
}
finalize()
在垃圾回收之前被调用。当对象超出范围时,它不会被调用。这意味着您无法知道何时甚至是否执行finalize()
。
例如:
如果您的程序在垃圾回收发生之前结束,则finalize()
将不会执行。因此,它应该作为备份过程用于确保其他资源的正确处理,或者用于特殊的应用程序,而不是作为程序在正常操作中使用的手段。
如https://wiki.sei.cmu.edu/confluence/display/java/MET12-J.+Do+not+use+finalizers所指出:
由于Java虚拟机(JVM)的执行时间不定,因此没有固定的时间来执行终结器。唯一的保证是任何执行终结器方法都将在关联对象变得不可达之后的某个时刻执行(在垃圾回收的第一个循环中检测到),并且在垃圾收集器的第二个循环期间回收关联对象的存储之前的某个时刻执行。对象的终结器执行可能会在对象变得不可达之后任意长的时间内被延迟。因此,在对象的finalize()方法中调用时关键功能,例如关闭文件句柄是有问题的。
尝试运行此程序以更好地理解
public class FinalizeTest
{
static {
System.out.println(Runtime.getRuntime().freeMemory());
}
public void run() {
System.out.println("run");
System.out.println(Runtime.getRuntime().freeMemory());
}
protected void finalize() throws Throwable {
System.out.println("finalize");
while(true)
break;
}
public static void main(String[] args) {
for (int i = 0 ; i < 500000 ; i++ ) {
new FinalizeTest().run();
}
}
}
finalize()
和垃圾回收并没有任何影响。 - ha9u63a7