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


当前回答

在最近与终结器方法搏斗之后(为了在测试期间处理连接池),我不得不说终结器缺少很多东西。使用VisualVM来观察以及使用弱引用来跟踪实际的交互,我发现以下事情在Java 8环境中是正确的(Oracle JDK, Ubuntu 15):

Finalize is not called immediately the Finalizer (GC part) individually owns the reference elusively The default Garbage Collector pools unreachable objects Finalize is called in bulk pointing to an implementation detail that there is a certain phase the garbage collector frees the resources. Calling System.gc() often does not result in objects being finalized more often, it just results in the Finalizer getting aware of an unreachable object more rapidly Creating a thread dump almost always result in triggering the finalizer due to high heap overhead during performing the heap dump or some other internal mechanism Finalization seams to be bound by either memory requirements (free up more memory) or by the list of objects being marked for finalization growing of a certain internal limit. So if you have a lot of objects getting finalized the finalization phase will be triggered more often and earlier when compared with only a few There were circumstances a System.gc() triggered a finalize directly but only if the reference was a local and short living. This might be generation related.

最后认为

最后确定方法是不可靠的,但只能用于一件事。您可以确保在垃圾收集之前关闭或释放对象,从而在正确处理涉及生命结束操作的更复杂生命周期的对象时实现故障安全。这是我能想到的一个值得我们去推翻它的原因。

其他回答

什么时候在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 finalize()方法不是析构函数,不应用于处理应用程序所依赖的逻辑。Java规范声明,不能保证在应用程序的生存期内调用finalize方法。

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

MyClass myObj;

try {
    myObj = new MyClass();

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

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

在最近与终结器方法搏斗之后(为了在测试期间处理连接池),我不得不说终结器缺少很多东西。使用VisualVM来观察以及使用弱引用来跟踪实际的交互,我发现以下事情在Java 8环境中是正确的(Oracle JDK, Ubuntu 15):

Finalize is not called immediately the Finalizer (GC part) individually owns the reference elusively The default Garbage Collector pools unreachable objects Finalize is called in bulk pointing to an implementation detail that there is a certain phase the garbage collector frees the resources. Calling System.gc() often does not result in objects being finalized more often, it just results in the Finalizer getting aware of an unreachable object more rapidly Creating a thread dump almost always result in triggering the finalizer due to high heap overhead during performing the heap dump or some other internal mechanism Finalization seams to be bound by either memory requirements (free up more memory) or by the list of objects being marked for finalization growing of a certain internal limit. So if you have a lot of objects getting finalized the finalization phase will be triggered more often and earlier when compared with only a few There were circumstances a System.gc() triggered a finalize directly but only if the reference was a local and short living. This might be generation related.

最后认为

最后确定方法是不可靠的,但只能用于一件事。您可以确保在垃圾收集之前关闭或释放对象,从而在正确处理涉及生命结束操作的更复杂生命周期的对象时实现故障安全。这是我能想到的一个值得我们去推翻它的原因。

protected void finalize() throws Throwable {} every class inherits the finalize() method from java.lang.Object the method is called by the garbage collector when it determines no more references to the object exist the Object finalize method performs no actions but it may be overridden by any class normally it should be overridden to clean-up non-Java resources ie closing a file if overridding finalize() it is good programming practice to use a try-catch-finally statement and to always call super.finalize(). This is a safety measure to ensure you do not inadvertently miss closing a resource used by the objects calling class protected void finalize() throws Throwable { try { close(); // close open files } finally { super.finalize(); } } any exception thrown by finalize() during garbage collection halts the finalization but is otherwise ignored finalize() is never run more than once on any object

引用自:http://www.janeg.ca/scjp/gc/finalize.html

你也可以看看这篇文章:

对象终结和清理

类,在其中重写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方法将被调用。