在Java中何时调用finalize()方法?

在Java中何时调用finalize()方法?,java,methods,garbage-collection,call,finalize,Java,Methods,Garbage Collection,Call,Finalize,我需要知道在JVM中何时调用该方法。我创建了一个测试类,当通过重写finalize()方法调用它时,它会写入一个文件。它没有被执行。有谁能告诉我它不执行的原因吗?当对象即将被垃圾回收时,会调用finalize方法。这可以在垃圾收集合格后的任何时间进行 请注意,对象完全可能永远不会被垃圾收集(因此永远不会调用finalize)。当对象永远不符合gc条件时(因为它在JVM的整个生命周期内都是可访问的),或者在对象符合gc条件到JVM停止运行之间没有垃圾收集实际运行时(这通常发生在简单的测试程序中),

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

当对象即将被垃圾回收时,会调用
finalize
方法。这可以在垃圾收集合格后的任何时间进行

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

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

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

Java中何时调用
finalize()
方法

finalize方法将在GC检测到对象不再可访问之后,以及在它实际回收对象使用的内存之前调用

  • 如果对象从未变得不可访问,则永远不会对其调用
    finalize()

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

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

  • 一旦GC检测到一个对象是不可访问和可终结的,它就会被放入终结队列中。终结通常与普通GC异步进行

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

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

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


我创建了一个测试类,当通过重写finalize()方法调用它时,该类会写入一个文件。它没有被执行。有人能告诉我它不执行的原因吗

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

  • 对象未被垃圾回收,因为它仍然可以访问
  • 对象不会被垃圾收集,因为在测试完成之前GC不会运行
  • 该对象由GC找到并放置在终结队列中,但在测试完成之前终结尚未完成
Java
finalize()
方法不是析构函数,不应用于处理应用程序所依赖的逻辑。Java规范指出,不能保证在应用程序的实时期间调用
finalize
方法

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

MyClass-myObj;
试一试{
myObj=新的MyClass();
// ...
}最后{
if(null!=myObj){
myObj.cleanup();
}
}

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

通常,最好不要依赖
finalize()
进行任何清理等

根据这本书(值得一读),它是:

当垃圾回收确定不再有对对象的引用时,由垃圾回收器对该对象调用

正如Joachim所指出的,如果对象总是可访问的,那么在程序的生命周期中可能永远不会发生这种情况

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

  • 每个类都从继承
    finalize()
    方法 java.lang.Object
  • 垃圾回收器在确定 不再引用该对象 存在
  • 对象finalize方法不执行任何操作,但它可能被 任何类别
  • 通常应该重写它来清理非Java资源 档案
  • 如果重写
    finalize()
    ,使用 尝试捕获finally语句并 始终调用
    super.finalize()
    。这 这是一个安全措施,以确保你这样做 不要不经意间错过了关闭一个 调用的对象所使用的资源 阶级

  • 垃圾收集期间
    finalize()
    引发的任何异常都会停止 最后定稿,但尚未完成
    protected void finalize() throws Throwable {}
    
    protected void finalize() throws Throwable {
         try {
             close();        // close open files
         } finally {
             super.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);
    }
    
    while ( true) {
        Book novel=new Book(true);
        //System.out.println(novel.checkedOut);
        //Runtime.getRuntime().runFinalization();
        novel.checkIn();
        new Book(true);
        //System.runFinalization();
        System.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
    
    // 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
    }
    
    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.");
                }
            }
        }
    }
    
        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.
    
    public class TestClass {    
        public TestClass() {
            System.out.println("constructor");
        }
    
        public void display() {
            System.out.println("display");
        }
        @Override
        public void finalize() {
            System.out.println("destructor");
        }
    }
    
    public class TestGarbageCollection {
        public static void main(String[] args) {
            while (true) {
                TestClass s = new TestClass();
                s.display();
                System.gc();
            }
        }
    }
    
    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();
                }
         }
    }
    
    protected void finalize(){
        // This is where the finalization code is entered
    }