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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2506488/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 08:36:26  来源:igfitidea点击:

When is the finalize() method called in Java?

javamethodsgarbage-collectioncallfinalize

提问by Rajesh Kumar J

I need to know when the finalize()method is called in the JVM. I created a test class which writes into a file when the finalize()method is called by overriding it. It is not executed. Can anybody tell me the reason why it is not executing?

我需要知道何时finalize()JVM. 我创建了一个测试类,它在finalize()通过覆盖调用方法时写入文件。它没有被执行。谁能告诉我它不执行的原因?

采纳答案by rsp

In general it's best not to rely on finalize()to do any cleaning up etc.

一般来说,最好不要依赖于finalize()做任何清理等。

According to the Javadoc(which it would be worth reading), it is:

根据Javadoc(值得一读),它是:

Called by the garbage collector on an object when garbage collection determines that there are no more references to the object.

当垃圾收集器确定不再有对对象的引用时,由垃圾收集器在对象上调用。

As Joachim pointed out, this may never happen in the life of a program if the object is always accessible.

正如 Joachim 指出的那样,如果对象始终是可访问的,那么这在程序的生命周期中可能永远不会发生。

Also, the garbage collector is not guaranteed to run at any specific time. In general, what I'm trying to say is finalize()is probably not the best method to use in general unless there's something specific you need it for.

此外,垃圾收集器不能保证在任何特定时间运行。一般来说,我想说的finalize()可能不是一般使用的最佳方法,除非您有特殊需要。

回答by Joachim Sauer

The finalizemethod is called when an object is about to get garbage collected. That can be at any time after it has become eligible for garbage collection.

finalize当对象即将被垃圾收集时调用该方法。这可以是在它符合垃圾收集条件之后的任何时间。

Note that it's entirely possible that an object never gets garbage collected (and thus finalizeis never called). This can happen when the object never becomes eligible for gc (because it's reachable through the entire lifetime of the JVM) or when no garbage collection actually runs between the time the object become eligible and the time the JVM stops running (this often occurs with simple test programs).

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

There are ways to tell the JVM to run finalizeon objects that it wasn't called on yet, but using them isn't a good idea either (the guarantees of that method aren't very strong either).

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

If you rely on finalizefor the correct operation of your application, then you're doing something wrong. finalizeshould onlybe used for cleanup of (usually non-Java) resources. And that's exactlybecause the JVM doesn't guarantee that finalizeis ever called on any object.

如果您依赖finalize应用程序的正确操作,那么您就做错了。finalize应该用于清理(通常是非 Java)资源。这正是因为 JVM 不保证会finalize在任何对象上调用。

回答by Stephen C

When is the finalize()method called in Java?

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

The finalize method will be called after the GC detects that the object is no longer reachable, and before it actually reclaims the memory used by the object.

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.

  • 如果一个对象永远不会变得不可访问,finalize()则永远不会被调用。

  • 如果 GC 不运行,则finalize()可能永远不会被调用。(通常,GC 仅在 JVM 确定可能有足够多的垃圾使其值得时才运行。)

  • 在 GC 确定特定对象不可达之前,可能需要一个以上的 GC 周期。(Java GC 通常是“分代”收集器……)

  • 一旦 GC 检测到一个对象不可访问且可终结,它就会被放置在终结队列中。终结通常与普通 GC 异步发生。

(The JVM spec actually allowsa JVM to neverrun finalizers ... provided that it doesn't reclaim the space used by the objects. A JVM that was implemented this way would be crippled / useless, but it this behavior is "allowed".)

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

The upshot is that it is unwise to rely on finalization to do things that have to be done in a definite time-frame. It is "best practice" not to use them at all. There should be a better (i.e. more reliable) way to do whatever it is you are trying to do in the finalize()method.

结果是,依靠最终确定来完成必须在确定的时间范围内完成的事情是不明智的。根本不使用它们是“最佳实践”。应该有一种更好(即更可靠)的方法来做您在该finalize()方法中尝试做的任何事情。

The only legitimate use for finalization is to clean up resources associated with objects that have been lost by application code. Even then, you should try to write the application code so that it doesn't lose the objects in the first place. (For example, use Java 7+ try-with-resourcesto ensure that close()is always called ...)

终结的唯一合法用途是清理与应用程序代码丢失的对象相关联的资源。即便如此,您也应该尝试编写应用程序代码,以便它首先不会丢失对象。(例如,使用 Java 7+ try-with-resources确保close()始终调用...)



I created a test class which writes into a file when the finalize() method is called by overriding it. It is not executed. Can anybody tell me the reason why it is not executing?

我创建了一个测试类,它在通过覆盖调用 finalize() 方法时写入文件。它没有被执行。谁能告诉我它不执行的原因?

It is hard to say, but there are a few possibilities:

很难说,但有几种可能:

  • The object is not garbage collected because it is still reachable.
  • The object is not garbage collected because the GC doesn't run before your test finishes.
  • The object is found by the GC and placed in the finalization queue by the GC, but finalization isn't completed before your test finishes.
  • 该对象不会被垃圾回收,因为它仍然可以访问。
  • 该对象不会被垃圾回收,因为 GC 不会在您的测试完成之前运行。
  • 该对象由 GC 找到并由 GC 放入终结队列,但在测试完成之前终结并未完成。

回答by rsp

The Java finalize()method is not a destructor and should not be used to handle logic that your application depends on. The Java spec states there is no guarantee that the finalizemethod is called at all during the livetime of the application.

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

What you problably want is a combination of finallyand a cleanup method, as in:

您可能想要的是finally和 清理方法的组合,例如:

MyClass myObj;

try {
    myObj = new MyClass();

    // ...
} finally {

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

回答by XpiritO

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
protected void finalize() throws Throwable {}
  • 每个类都finalize()从 java.lang.Object继承方法
  • 当垃圾收集器确定不再存在对该对象的引用时,将调用该方法
  • Object finalize 方法不执行任何操作,但它可能被任何类覆盖
  • 通常应该覆盖清理非 Java 资源,即关闭文件
  • 如果覆盖finalize(),使用 try-catch-finally 语句并始终调用super.finalize(). 这是一种安全措施,可确保您不会无意中错过关闭调用类的对象所使用的资源

    protected void finalize() throws Throwable {
         try {
             close();        // close open files
         } finally {
             super.finalize();
         }
     }
    
  • finalize()垃圾收集期间抛出的任何异常都会停止完成,但会被忽略

  • finalize()永远不会在任何对象上运行超过一次

quoted from: http://www.janeg.ca/scjp/gc/finalize.html

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

You could also check this article:

您还可以查看这篇文章:

回答by giri

finalizemethod is not guaranteed.This method is called when the object becomes eligible for GC. There are many situations where the objects may not be garbage collected.

不保证finalize方法。当对象符合 GC 条件时调用此方法。在很多情况下,对象可能不会被垃圾回收。

回答by user1623624

finalize will print out the count for class creation.

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();

As you can see. The following out put show the gc got executed first time when the class count is 36.

如你看到的。以下输出显示当类计数为 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

回答by Tushar Trivedi

An Object becomes eligible for Garbage collection or GC if its not reachable from any live threads or any static refrences in other words you can say that an object becomes eligible for garbage collection if its all references are null. Cyclic dependencies are not counted as reference so if Object A has reference of object B and object B has reference of Object A and they don't have any other live reference then both Objects A and B will be eligible for Garbage collection. Generally an object becomes eligible for garbage collection in Java on following cases:

如果对象无法从任何活动线程或任何静态引用访问,则该对象有资格进行垃圾收集或 GC,换句话说,如果对象的所有引用均为空,则可以说该对象有资格进行垃圾收集。循环依赖不被算作引用,所以如果对象 A 有对象 B 的引用,对象 B 有对象 A 的引用,并且它们没有任何其他实时引用,那么对象 A 和 B 都将有资格进行垃圾收集。通常,在以下情况下,对象有资格在 Java 中进行垃圾回收:

  1. All references of that object explicitly set to null e.g. object = null
  2. Object is created inside a block and reference goes out scope once control exit that block.
  3. Parent object set to null, if an object holds reference of another object and when you set container object's reference null, child or contained object automatically becomes eligible for garbage collection.
  4. If an object has only live references via WeakHashMap it will be eligible for garbage collection.
  1. 该对象的所有引用显式设置为 null 例如 object = null
  2. 对象是在块内创建的,一旦控制退出该块,引用就会超出范围。
  3. 父对象设置为 null,如果一个对象持有另一个对象的引用,并且当您将容器对象的引用设置为 null 时,子对象或包含的对象将自动成为垃圾收集的合格对象。
  4. 如果一个对象只有通过 WeakHashMap 的实时引用,它将有资格进行垃圾收集。

回答by Hao Deng

Check out Effective Java, 2nd edition page 27. Item 7: Avoid finalizers

查看 Effective Java,第 2 版第 27 页。 第 7 项:避免终结器

Finalizers are unpredictable, often dangerous, and generally unnecessary.never do anything time-critical in a finalizer. never depend on a finalizer to update critical persistent state.

终结器是不可预测的,通常是危险的,而且通常是不必要的。永远不要在终结器中做任何时间紧迫的事情。从不依赖终结器来更新关键的持久状态。

To terminate a resource, use try-finally instead:

要终止资源,请改用 try-finally:

// try-finally block guarantees execution of termination method
Foo foo = new Foo(...);
try {
    // Do what must be done with foo
    ...
} finally {
    foo.terminate(); // Explicit termination method
}
// try-finally block guarantees execution of termination method
Foo foo = new Foo(...);
try {
    // Do what must be done with foo
    ...
} finally {
    foo.terminate(); // Explicit termination method
}

回答by techloris_109

Since there is an uncertainity in calling of finalize() method by JVM (not sure whether finalize() which is overridden would be executed or not), for study purposes the better way to observe what happens when finalize() is called, is to force the JVM to call garbage collection by command System.gc().

由于 JVM 调用 finalize() 方法存在不确定性(不确定是否会执行被覆盖的 finalize()),出于研究目的,观察调用 finalize() 时会发生什么的更好方法是强制 JVM 通过命令调用垃圾收集System.gc()

Specifically, finalize() is called when an object is no longer in use. But when we try to call it by creating new objects there is no certainty of its call. So for certainty we create a nullobject cwhich obviously has no future use, hence we see the object c's finalize call.

具体来说,当不再使用对象时调用 finalize()。但是当我们尝试通过创建新对象来调用它时,它的调用是不确定的。因此,对于把握我们创建了一个null对象c,这显然是没有前途的使用,因此我们看到物体c的敲定电话。

Example

例子

class Car {

    int maxspeed;

    Car() {
        maxspeed = 70;
    }

    protected void finalize() {

    // Originally finalize method does nothing, but here we override finalize() saying it to print some stmt
    // Calling of finalize is uncertain. Difficult to observe so we force JVM to call it by System.gc(); GarbageCollection

        System.out.println("Called finalize method in class Car...");
    }
}

class Bike {

    int maxspeed;

    Bike() {
        maxspeed = 50;
    }

    protected void finalize() {
        System.out.println("Called finalize method in class Bike...");
    }
}

class Example {

    public static void main(String args[]) {
        Car c = new Car();
        c = null;    // if c weren`t null JVM wouldn't be certain it's cleared or not, null means has no future use or no longer in use hence clears it
        Bike b = new Bike();
        System.gc();    // should clear c, but not b
        for (b.maxspeed = 1; b.maxspeed <= 70; b.maxspeed++) {
            System.out.print("\t" + b.maxspeed);
            if (b.maxspeed > 50) {
                System.out.println("Over Speed. Pls slow down.");
            }
        }
    }
}

Output

输出

    Called finalize method in class Car...
            1       2       3       4       5       6       7       8       9
    10      11      12      13      14      15      16      17      18      19
    20      21      22      23      24      25      26      27      28      29
    30      31      32      33      34      35      36      37      38      39
    40      41      42      43      44      45      46      47      48      49
    50      51Over Speed. Pls slow down.
            52Over Speed. Pls slow down.
            53Over Speed. Pls slow down.
            54Over Speed. Pls slow down.
            55Over Speed. Pls slow down.
            56Over Speed. Pls slow down.
            57Over Speed. Pls slow down.
            58Over Speed. Pls slow down. 
            59Over Speed. Pls slow down.
            60Over Speed. Pls slow down.
            61Over Speed. Pls slow down.
            62Over Speed. Pls slow down.
            63Over Speed. Pls slow down.
            64Over Speed. Pls slow down.
            65Over Speed. Pls slow down.
            66Over Speed. Pls slow down.
            67Over Speed. Pls slow down.
            68Over Speed. Pls slow down.
            69Over Speed. Pls slow down.
            70Over Speed. Pls slow down.

Note- Even after printing upto 70 and after which object b is not being used in the program, there is uncertainty that b is cleared or not by JVM since "Called finalize method in class Bike..." is not printed.

注意- 即使在打印到 70 之后并且程序中没有使用对象 b 之后,也不确定 b 是否被 JVM 清除,因为“在 Bike 类中调用了finalize 方法...”没有打印。