我需要知道什么时候在JVM中调用finalize()方法。我创建了一个测试类,当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();
            }
     }
}

其他回答

最终确定方法是不保证的。当对象符合GC条件时调用此方法。在许多情况下,对象可能不会被垃圾收集。

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

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

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

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

什么时候在Java中调用finalize()方法?

finalize方法将在GC检测到对象不再可达之后调用,并且在它实际回收对象所使用的内存之前调用。

If an object never becomes unreachable, finalize() will never be called on it. If the GC doesn't run then finalize() may never be called. (Normally, the GC only runs when the JVM decides that there is likely to enough garbage to make it worthwhile.) It may take more than one GC cycle before the GC determines that a specific object is unreachable. (Java GCs are typically "generational" collectors ...) Once the GC detects an object is unreachable and finalizable, it is places on a finalization queue. Finalization typically occurs asynchronously with the normal GC.

(JVM规范实际上允许JVM永远不运行终结器……前提是它不回收对象所使用的空间。以这种方式实现的JVM将是残废的/无用的,但这种行为是“允许的”。)

其结果是,依赖最终确定来完成必须在特定时间框架内完成的事情是不明智的。根本不使用它们是“最佳实践”。应该有更好的(即更可靠的)方法来做你在finalize()方法中试图做的事情。

终结的唯一合法用途是清理应用程序代码丢失的与对象相关的资源。即使这样,您也应该尝试编写应用程序代码,使其在一开始就不会丢失对象。(例如,使用Java 7+ try-with-resources来确保close()总是被调用…)


我创建了一个测试类,当finalize()方法被重写时写入文件。它没有被执行。有人能告诉我为什么它不能执行吗?

这很难说,但有几种可能性:

对象不会被垃圾收集,因为它仍然是可达的。 对象不会被垃圾收集,因为GC在测试结束之前不会运行。 对象由GC找到,并由GC放置在终结队列中,但是在测试结束之前,终结不会完成。

Java allows objects to implement a method called finalize() that might get called. finalize() method gets called if the garbage collector tries to collect the object. If the garbage collector doesn't run, the method doesn't get called. If the garbage collector fails to collect the object and tries to run it again, the method doesn't get called in the second time. In practice, you are highly unlikely to use it in real projects. Just keep in mind that it might not get called and that it definitely won't be called twice. The finalize() method could run zero or one time. In the following code, finalize() method produces no output when we run it since the program exits before there is any need to run the garbage collector.

Java finalize()方法不是析构函数,不应用于处理应用程序所依赖的逻辑。Java规范声明,不能保证在应用程序的生存期内调用finalize方法。

你可能想要的是一个finally和cleanup方法的组合,如:

MyClass myObj;

try {
    myObj = new MyClass();

    // ...
} finally {
    if (null != myObj) {
        myObj.cleanup();
    }
}

这将正确处理MyClass()构造函数抛出异常时的情况。