我需要知道什么时候在JVM中调用finalize()方法。我创建了一个测试类,当finalize()方法被重写时写入文件。它没有被执行。有人能告诉我为什么它不能执行吗?


当前回答

finalize方法在对象即将被垃圾收集时被调用。这可以在它有资格进行垃圾收集之后的任何时间进行。

注意,完全有可能一个对象永远不会被垃圾收集(因此finalize永远不会被调用)。当对象永远不符合gc条件(因为在JVM的整个生命周期内都可以访问它),或者在对象符合条件到JVM停止运行之间没有实际运行垃圾收集时(这种情况经常发生在简单的测试程序中),就会发生这种情况。

有一些方法可以告诉JVM在尚未调用的对象上运行finalize,但使用这些方法也不是一个好主意(该方法的保证也不是很强)。

如果您依赖finalize来实现应用程序的正确操作,那么您就做错了一些事情。finalize只能用于清理(通常是非java)资源。这正是因为JVM不能保证finalize在任何对象上都被调用。

其他回答

Finalize将打印出类创建的计数。

protected void finalize() throws Throwable {
    System.out.println("Run F" );
    if ( checkedOut)
        System.out.println("Error: Checked out");
        System.out.println("Class Create Count: " + classCreate);
}

main

while ( true) {
    Book novel=new Book(true);
    //System.out.println(novel.checkedOut);
    //Runtime.getRuntime().runFinalization();
    novel.checkIn();
    new Book(true);
    //System.runFinalization();
    System.gc();

如你所见。下面的输出显示了类计数为36时第一次执行的gc。

C:\javaCode\firstClass>java TerminationCondition
Run F
Error: Checked out
Class Create Count: 36
Run F
Error: Checked out
Class Create Count: 48
Run F

Sometimes when it is destroyed, an object must make an action. For example, if an object has a non-java resource such as a file handle or a font, you can verify that these resources are released before destroying an object. To manage such situations, java offers a mechanism called "finalizing". By finalizing it, you can define specific actions that occur when an object is about to be removed from the garbage collector. To add a finalizer to a class simply define the finalize() method. Java execution time calls this method whenever it is about to delete an object of that class. Within the finalize method() you specify actions to be performed before destroying an object. The garbage collector is periodically searched for objects that no longer refer to any running state or indirectly any other object with reference. Before an asset is released, the Java runtime calls the finalize() method on the object. The finalize() method has the following general form:

protected void finalize(){
    // This is where the finalization code is entered
}

使用protected关键字,finalize()类之外的代码可以阻止对finalize()的访问。 务必要理解finalize()是在垃圾收集之前调用的。例如,当对象离开作用域时,它不会被调用。这意味着您无法知道finalize()何时或是否将执行。因此,程序必须提供其他方法来释放系统资源或对象使用的其他资源。不应该依赖finalize()来实现程序的正常运行。

正如在https://wiki.sei.cmu.edu/confluence/display/java/MET12-J.+Do+not+use+finalizers上指出的那样,

There is no fixed time at which finalizers must be executed because time of execution depends on the Java Virtual Machine (JVM). The only guarantee is that any finalizer method that executes will do so sometime after the associated object has become unreachable (detected during the first cycle of garbage collection) and sometime before the garbage collector reclaims the associated object's storage (during the garbage collector's second cycle). Execution of an object's finalizer may be delayed for an arbitrarily long time after the object becomes unreachable. Consequently, invoking time-critical functionality such as closing file handles in an object's finalize() method is problematic.

最终确定方法是不保证的。当对象符合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();
        }
    }
}

当内存被转储对象重载时,gc将调用finalize方法

运行并查看控制台,在那里你不会发现finalize方法被频繁调用,当内存超载时,finalize方法将被调用。