Frage

Now, I wrote a simple code.

public class ToDo {

    ToDo instance;

    public ToDo () {

    }

    void foo() {
        System.out.println("foo.");
    }

    void bar() {
        System.out.println("bar.");
    }

    public static void main(String args[]) throws Throwable {

        ToDo inDo = new ToDo();
        inDo.foo();
        inDo.finalize();
        inDo.bar();
    }
}
  1. The finalize in Object.java is an empty function, Where is the heavy work of cleaning the object happening ?

  2. Finalizer is called when object is garbage collected. Which means it should not call 'bar' How is bar still being printed.

War es hilfreich?

Lösung

The finalize in Object.java is an empty function, Where is the heavy work of cleaning the object happening?

Objects in Java don't normally get "cleaned". In C++, the most common task of a destructor is to release allocated memory, but in Java, the VM takes care of garbage-collecting unused allocations. Finalizers can be used to release non-managed resources, such as native OS UI components, but you can't rely on them to take care of this job, since they may be called long after the object stops being used or not at all. Instead, you should have a method such as dispose() or close() (see Closeable), and you can optionally call that method from a finalizer as a kind of safety net, but your client code should be responsible for calling it.

Finalizer is called when object is garbage collected. Which means it should not call 'bar' How is bar still being printed.

The object is still live until the finalizer finishes, so calling bar is acceptable. As above, you can use the finalizer to call cleanup methods in case your client left something open.

Andere Tipps

You should not be calling finalize() yourself. The JVM calls this if and when it is supposed to do so. This method does not cause the object to be GC'd but rather does cleaning up, and again, is not something ordinary mortal code is supposed to call.

The finalize in Object.java is an empty function, Where is the heavy work of cleaning the object happening ?

Inside the JVM, as part of the garbage collector. You don't have access to any of this logic.

Finalizer is called when object is garbage collected. Which means it should not call 'bar' How is bar still being printed.

Not exactly. finalize() is called at any point between the moment the object has no references (and thus is ready for collection) and the moment the VM decides to effectively reclaim it, but before effectively doing it. This is important because finalize() could not only print "bar", but even establish references (by executing AClass.aStaticField= this ;, as a very simple example) that make the object or other objects previously eligible for collection again "alive". For this reason, the object's eligibility for garbage collection is checked again after finalize() and collection possibly aborted. By doing this, objects can refuse to be garbage collected, but not forever (see below).

Additional ideas that could help understanding finalize()?

  1. It's not equivalent to a destructor at all.
  2. It exists mainly for historical reasons. The original idea was to give objects a chance of cleaning up resources (TCP connections, open files, etc.) before being collected. However, the period that can pass between object "release" and finalize() is so variable that explicit resource de-allocation through close() methods became the preferred ("Javatic"?) way and finalize() use has been discouraged. In fact, many JVMs do not call any finalize() method when terminating.
  3. One good example of the preference I mention above is the "try with resources" construct introduced in Java 7. In contrast, nothing has been done to correct the challenges presented by finalize(). Ever.
  4. The ability of finalize() to "resurrect" not only its own object, but also other objects has consequences not fully specified. What has been specified is: "The finalize method is never invoked more than once by a Java virtual machine for any given object.". This means that if finalize() "resurrects" its own object, it will not be called a second time even the object is ready for collection again. Very curious behavior to say the least. Random in fact if two objects interplayed this way, as Java doesn't guarantee any order while collecting objects.
  5. In summary: do not use finalize(). If you did, you would be one of the first persons depending on it for anything. The idea was good, in principle, but there was no way of anticipating the consequences that became apparent in time. Do define explicit close() methods for resource cleanup. In some cases, cleanup threads that monitor resource usage can also be useful.

PS: Something very similar happened with Thread.suspend(), Thread.resume(), Thread.stop(), and Thread.destroy(). Very nice ideas that practice proved a nightmate in terms of application and JVM stability. The only difference is that these Thread methods have been officially deprecated because their impact is (debatably) bigger.

finalize is called by the garbage collector when the object is about to be collected.

You calling finalize don't have any effect at all. (It is like calling any other method).

The finalize in Object.java is an empty function, Where is the heavy work of cleaning the object happening ?

This is an empty method in Object class but if you to make use of its purpose then you need to override it in your class.

Finalizer is called when object is garbage collected. Which means it should not call 'bar' How is bar still being printed.

finalize methods are called by jvm before the object is getting garbage collected. But being a simple method, you can always call it directly. But calling finalize directly does not make the object ready for or getting garbage collected. Hence doing this :

    inDo.finalize();
    inDo.bar();

will still work because inDo object is still referenced or active and not garbage collected.

  1. If you want to see finalize work run this test

    public class Test1 {

    protected void finalize()  {
        System.out.println("finalize");
    }
    
    public static void main(String[] args) throws Exception {
        new Test1();
        System.gc();
    }
    

    }

Note that System.gc does not guarantee that GC will run but it always does on my HotSpot VM.

  1. finalize is a callback from JVM, it should be overriden with some meaningful implementation, eg java.io.FileInputStream implements finalize to close FileInputStream which program failed to close. There is an article in Effective Java Item.7 Avoid finalizers which explains problems with finalize in detail
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top