PS: I do know how to cleanup correctly, without depending on finalize().
Does Java not guarantee that on program exit, proper garbage collection will be done?
E.g. lets say I’ve kept some data in cache instead of serializing it frequently, I also implemented finalize() with the hope that if due to whatever reason (except crash) my program exits gracefully, then the cache would be written to DB/file/some-storage by my code in finalize() method. But according to following little experiment it seems like JVM doesn’t cleanup memory “gracefully”, it just exits.
Java spec (see program exit) says NOTHING abt how memory / gc is handled on exit. Or should I have been looking at a different section of the spec?
Take the following example (output at the end) using 1.6.0.27 64 bits, on Windows 7
public class Main {
// just so GC might feel there is something to free..
private int[] intarr = new int[10000];
public static void main(String[] args) {
System.out.println("entry");
Main m = new Main();
m.foo();
m = new Main();
// System.gc();
m.foo();
m = null;
// System.gc();
System.out.println("before System.exit(0);");
System.exit(0);
}
@Override
protected void finalize() throws Throwable {
System.out.println("finalize()");
super.finalize();
}
public void foo() { System.out.println("foo()"); }
}
/*
* Prints:
* entry
* foo()
* foo()
* before System.exit(0);
*/
Variations:
- If I uncomment any one
System.gc()then nofinalize()is called. - If I uncomment both
System.gc()thenfinalize()is called twice. - Whether
System.exit()is called or not has no effect on whetherfinalize()is called or not.
No, Java does not guarantee that on program exit the GC will trigger. If you want an operation to peform on exit use
Runtime.addShutdownHookmethod. Read this Sun article on what the SPEC says.