Is Object memory freed when we explicitly call finalize() on it? [duplicate]
Asked Answered
D

3

2

As far as my understanding goes finalize() and GC are two different aspects. GC uses finalize() method to free Object memory. We cannot state when GC will occur(even if we explicitly call System.gc()). But we can explicitly call finalize() on an Object.

Will the function be executed immediately(memory freed) or it waits till GC
occurs like System.gc() call?

Also as per the docs the finalize method is never invoked more than once by a Java virtual machine for any given object.

So what happens when we call finalize() first and GC happens at a later point of time.

If object memory is not freed on explicit call to object.finalize() then would't 
it being called again in the GC process violate the calling only once rule? 
Durwin answered 29/8, 2013 at 12:8 Comment(1)
@duffymo not really...Squirmy
U
7

You have got it completely wrong.

Short answer: finalize() is a means to clean up resources (such as open files) just before the object is ready for garbage collection ( when no object has strong reference to it). It might/not be called. It is one step ahead of memory deallocation.

Long answer:

There is a separate daemon thread called as finalizer thread which is responsible for calling finalize() method . Finalization queue is the queue where objects which are ready to be called finalize() method are placed.

  1. When an Object is created, JVM checks if the user has overridden the finalize() method. If it has then it internally notes that this particular object has finalize() method.

When an object is ready for garbage collection, then the garbage collector thread checks if this particular object has finalize() from table mentioned in (1).

  • 2a) If it doesn’t then it is sent for garbage collection.

    2b) It is has, then it is added to the finalization queue. And it removes the entry of the object from the table (1).

Finalizer thread keeps polling the queue. For every object in the queue, its finalize() method is called. After calling the finalize() cycle from (2) is again repeated. If this object still has no strong reference, then sent for GC. If it has then ALWAYS (2a) is called because the entry was deleted in (2b)

Basically finalize() method is only called once.

So what’s the issue with the above cycle?

From (1). Its take extra time in object creation. Memory allocation in Java is 5x to 10x faster than malloc/calloc etc. All the time gained is lost in the procedure of noting the object in the table etc. I once tried it. Create 100000 objects in a loop and measure the time taken for program to terminate in 2 cases: One with no finalize(), Second with finalize(). Found it to be 20% faster.

From (2b): Memory Leakage and Starvation. If the object in the queue has references to a lot of memory resources, then all those objects wont get freed unless this object is ready for GC.If all the objects are heavy weight objects, then there can be a shortage.

From (2b): Because finalize() is called only once, what if in teh finalize() you had a strong reference to “this” object. Next time the object’s finalie() is never called hence can leave the object in an inconsistent state.

If inside finalize() an exception is thrown, it is ignored.

You do not know when finalize() is called as you have no control over when GC is called. Sometimes it might happen that you are printing the value’s in finalize() but the output is never shown, because your program might have got terminated by the time finalize() is called.

Hence avoid using it. Instead create a method say dispose() which will close the necessory resources or for final log etc.

Urger answered 29/8, 2013 at 12:11 Comment(7)
So we cannot explicitly call finalize() on any object and even if we do it will only execute when GC happens. Is that right?Durwin
If you wish to call you call always call it. But it is not advisable at all. And if you call it, it will executed like any other method call. The GC call's it later (though it might or might not appear). Read above for more infoUrger
@Urger - +1 (especially for first sentence), but please review my edit. You described what finalize() does, I described why someone might think they need it.Hymettus
What does the statement ' JVM checks if the object has a finalize() method' mean? All objects have finalize() method since all extend Object class?Durwin
It means if you have explicitly defined it or not. Edited it.,Urger
The specification has a notion of “trivial” finalizer that is a) the finalize() method declared by java.lang.Object, b) an empty finalize() method, or c) a finalize() method consisting of a sole super.finalize() call to another trivial finalize method. So when an object is created, the JVM checks if its class has a finalize method that is “not trivial”.Septuor
@Septuor Wow. Thanks. I wasn't aware of this fact. I have learnt so much from your answers :). Thanks you!Urger
P
1

As per docs:

The finalize method is never invoked more than once by a Java virtual machine for any given object.

However, you cannot force GC to run, you can just kindly ask it via System.gc(). So best approach is putting resource-freeing code into finalize() method when overriding.

Pocketful answered 29/8, 2013 at 12:12 Comment(1)
still depends on the jvm but this is basicly the answerOozy
D
1

Answers are in Object.finalize API

1) GC calls finalize() so finalize() and GC are NOT two different aspects

2) You should not call finalize manually, but if you do it will not will not free any memory and it will not affect GC behaviour

3) It is said that it's guaranteed that GC will not call finalize twice, our calls do not count

Damara answered 29/8, 2013 at 12:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.