Search code examples
javagarbage-collection

Overriden method finalize() isn't called for all of the garbage objects


I have a class Tank that has an overridden method finalize(), which prints the message:

@Override
protected void finalize() {
    if (full) {  // -full : boolean
        System.out.println("Error: tank " + id + " must be empty at cleanup"); // -id: int
    }
    else { 
        System.out.println("Tank " + id + " cleaned up OK");  // -id: int
    }
}

Then I create an array with Tanks and instatiate each of them and in a loop I am deleting every link:

for (int i = 0; i < 5; i++) {
    tanks[i] = null;
}
System.gc()

Every run I get a different combination of messages. I understand that I cannot be sure if the call System.gc() brings the garbage collector, however why do I have messages only for some objects but not for all? If garbage collector comes, doesn't it collect all "dead" links?

Examples of the output:

  1. No 0 tank
Tank 4 cleaned up OK
Tank 3 cleaned up OK
Error: tank 2 must be empty at cleanup
Error: tank 1 must be empty at cleanup
  1. Only tank 4:
Tank 4 cleaned up OK

Solution

  • If garbage collector comes, doesn't it collect all "dead" links?

    Short answer: no

    Longer answer: there are no guarantees of what will happen at garbage collection time. You have to understand that modern JVMs have implemented several GC algorithms which are usually very complex. What they will do and when will vary wildly. We don't which one your version of the JVM in your particular environment is using right now. One thing these complex algorithms try to avoid is doing a full garbage collection, where most objects that are not referenced are garbage collected. That's because such full GC events mean that the JVM needs to be stopped for some time to ensure everything is consistent. Those pause impact application performance and can cause issues like timeouts or freezes. Developers of GC algorithms try very hard to avoid those issues. So you should not assume a GC implementation will work in the way you are expecting.

    I recommend to read about the different GC algorithms current JVM implement to understand better their complexities.