Hi,

can anybody tell me why finalize is not called in this example?
I expect finalize to get called and write the file "final.txt".
I do see this file if I call finalize explicitly (see commented out line in main).

A Java VM will be started and stopped when I run this example, right?
Am I missing something?

Maarten

// File Main.java
package testgc;

public class Main {
    public static void main(String[] args) throws Throwable {
        if (true) {
            Trash trash = new Trash();
            // trash.finalize();
        }
        System.gc();
    }
}

// File Trash.java (i.e. this code is not in file Main.java)
package testgc;

import java.io.FileOutputStream;
import java.io.PrintWriter;

public class Trash {

    @Override
    protected void finalize() throws Throwable {
        PrintWriter out = new PrintWriter(new FileOutputStream("final.txt"));
        out.println("Finalizing");
        out.close();
    }
}
Trash t = new Trash();
t=null;
System.gc();
System.runFinalization();

does run the finalization. Finalize is a bit of a tricky thing and really shouldn't be relied upon as a cleanup mechanism. If you need to close resources, you should put explicit methods in for that and call them when required. You can read more about this here: http://www.codeguru.com/java/tij/tij0051.shtml#Index296

commented: Good Post +7

Thanks, the codeguru link describes the issues very well!

Interestingly, it seems that the call to runFinalization() makes no difference, but the call to trash = null does!

public class Main {
    public static void main(String[] args) throws Throwable {
        if (true) {
            Trash trash = new Trash();
            // this line makes a difference between calling finalize or not
            trash = null;
        }
        System.gc();
        // having this line or not makes no difference
        System.runFinalization();
    }
}

I now understand that Java may omit the call to finalize for performance reasons. It is a pity that runFinalization makes no difference
(and runFinalizationOnExit is unsafe), it would be very useful in testing that a module properly cleans up its data:

MyModule m = new MyModule(); // creates 10 instances of class XYZ
m.doStuffWith( someOtherModule );
m.cleanUp(); // how to test that 10 instances of XYZ have become obsolete?

Anyway, thanks, I'll do some more research on this.
Maarten

Keep in mind that you are performing a very limited scope 'test' with that finalization. It is a single trivial object that is only in scope while main() is executing and goes out of scope just before the JVM exits, which is not reflective of most other runtime conditions. There is seldom a need to explicitly set a reference to null in that manner. Once it goes out of scope and there are no longer any active references to it, it will be garbage collected and finalized by the JVM as needed.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.