3

I been reading the book OCA Java SE 8 Programmer I Exam Guide by Kathy Sierra + Bert Bates.

There is something about the finalize method I don't get it quite well. It states on page 218:

Calling finalize() can actually result in saving an object from deletion.

Later on page 222:

You can make an object ineligible for GC from within finalize().

English is not my native language, but what I understand in both scenarios is that the finalize() method can prevent the object from being garbage collected? Is this so? Or am I misinterpreting it?

chiperortiz
  • 4,751
  • 9
  • 45
  • 79
  • 1
    If you were to save somewhere a reference to the object in `finalize`, I would think that would prevent it from being GC'd. – Carcigenicate Oct 31 '19 at 13:16

3 Answers3

5

This is really more of a theoretical thing: objects are eligible for garbage collection when they aren't referenced from other live objects anymore.

Thus: you could try to create such a reference within finalize(). Which would then theoretically prevent the object from being removed.

There is actually a "pattern name" for that: object resurrection. Now, if this is a pattern, or more of an anti pattern is open for debate.

(personally: I would never do that, and I have never been in a situation where it would have been necessary to use this pattern)

GhostCat
  • 137,827
  • 25
  • 176
  • 248
  • Apart from this being a way to invoke some logic when Garbage Collector fiers and tries to collect the object in question, this really does not differ from simply storing a "global" reference to said object, correct? – Fureeish Oct 31 '19 at 13:23
  • 1
    @Fureeish Bear in mind that `finalize()` is only invoked once (if it's invoked at all). After referencing again the object, and later de-referencing, the `finalize()` method is not invoked again and the object is subject to being directly discarded. – M A Oct 31 '19 at 13:32
  • 1
    @Fureeish Well, when you add references in some "global store", you would do that at some **prior** point in time. So theoretically, that object **never** gets eligible, thus its finalize() will never be called. – GhostCat Oct 31 '19 at 13:34
  • @manouti the `finalize()` method of that object is not invoked again, but it doesn’t have to resurrect the `this` instance but could resurrect another object only reachable by this object under finalization. It could be stored into another object with a `finalize()`, to resurrect it an arbitrary number of times. But in fact, the invocation of `finalize()` **is** already a resurrection. Put an infinite loop into it, and the object stays forever, without the need to store a global reference. Do this as often as you have finalizer threads and *all* objects with nontrivial `finalize()` stay alive. – Holger Nov 25 '19 at 11:55
2

Finalize is a method called by JVM and not by the user, this method is executed just before an object is being garbage collected, you can override the finalize method to do cleanup operations before the object is disposed or as the book stated it is possible that you can prevent the object from being garbage collected.

You can refer below code as an example of saving an object from being garbage collected.

class Example { 

    static Example y; 

    void func() { 
        Example x = new Example(); 
    } 

    pubic void finalize() { 

        y = this; // Putting the reference id 
        // of the current object 
        // into the static variable y 

        System.out.println("The object won't be collected by the garbage collector"); 

    } 

    public static void main(String a[]) {
        func(); // function called 
    } 
}
xenteros
  • 15,586
  • 12
  • 56
  • 91
Shubham Saraswat
  • 559
  • 4
  • 11
  • yes like this topic shows. https://dzone.com/articles/java-immortal-objects-and-object-resurrection – chiperortiz Oct 31 '19 at 13:32
  • @chiperortiz yes, when the method finalize is called you can always refer to the object being destroyed using this keyword and do whatever you require from that particular object, one such usage is resurrection. – Shubham Saraswat Oct 31 '19 at 13:35
0

Well, that is true.

finalize() method is being called when GC decides that the object should be deleted but it doesn't mean, that the object will be removed anyway right after finalize finishes.

IT DOESN'T WORK THIS WAY:
_________________________
IF shouldBeRemoved(object)
   object.finalize();
   remove(object);

After finalize executes, GC will check once more if the object should still be removed. To qualify for removal, an object shouldn't be referenced from any object that is reachable from the root objects.

IT WORKS THIS WAY
_________________
LABEL
IF shouldBeRemoved(object)
    object.finalize();
    IF shouldBeRemoved(object)
        remove(object);
    ELSE
        GOTO LABEL

Let's imagine the following case:

class Foo {
    Application a;

    Foo(){};

    @Override
    public void finalize() {
        this.a = Application.getInstance();
    }
}

Where Application is a class which represents the root object of the Application. In this case, as a is still reachable, the object of class Foo that qualified for removal right before, has just resurrected.

IMPORTANT REMARK

You are not guaranteed, that the finalize will be called, as it requires another object to take care of finalize method being called, so in case there is no enough free space on the heap, object might be destroyed without calling finalize.

xenteros
  • 15,586
  • 12
  • 56
  • 91
  • 1
    How does assigning the `Application` instance to an instance variable keep that same instance reachable? It isn't assigning a reference to `this` to some other location, so I don't see how the instance is reachable via its own instance variable. – Lew Bloch Oct 31 '19 at 19:10
  • 1
    Regarding "object might be destroyed without calling `finalize`", that is false. Also, I do not understand "it requires another object to take care of `finalize` method being called". What other object? That doesn't ring true either. – Lew Bloch Oct 31 '19 at 19:12