Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does Java GC call finalize() method?

As far as I understand, GC starts with some set of initial objects (stack, static objects) and recursively traverses it building a graph of reachable objects. Then it marks the memory taken by these objects as occupied and assumes all the rest of the memory free.

But what if this 'free' memory contains an object with finalize method? GC has to call it, but I don't see how it can even know about objects that aren't reachable anymore.

I suppose GC can keep track of all 'finalizable' objects while they are alive. If so, does having finalizable objects make garbage collecting more expensive even when they are still alive?

like image 362
Vlad Shevchenko Avatar asked Dec 22 '16 18:12

Vlad Shevchenko


2 Answers

Consider the Reference API.

It offers some references with special semantics to the GC, i.e Weak, Soft, and Phantom references. There’s simply another non-public type of special reference, for objects needing finalization.

Now, when the garbage collector traverses the object graph and encounters such a special reference object, it will not mark objects reachable through this reference as strongly reachable, but reachable with the special semantics. So if an object is only finalizer-reachable, the reference will be enqueued, so that one (or one of the) finalizer thread(s) can poll the queue and execute the finalize() method (it’s not the garbage collector itself calling this method).

In other words, the garbage collector never processes entirely unreachable objects here. To apply a special semantic to the reachability, the reference object must be reachable, so the referent can be reached through that reference. In case of finalizer-reachability, Finalizer.register is called when an object is created and it creates an instance of Finalizer in turn, a subclass of FinalReference, and right in its constructor, it calls an add() method which will insert the reference into a global linked list. So all these FinalReference instances are reachable through that list until an actual finalization happens.

Since this FinalReference will be created right on the instantiation of the object, if its class declares a non-trivial finalize() method, there is already some overhead due to having a finalization requirement, even if the object has not collected yet.

The other issue is that an object processed by a finalizer thread is reachable by that thread and might even escape, depending on what the finalize() method does. But the next time, this object becomes unreachable, the special reference object does not exist anymore, so it can be treated like any other unreachable object.

This would only be a performance issue, if memory is very low and the next garbage collection had to be performed earlier to eventually reclaim that object. But this doesn’t happen in the reference implementation (aka “HotSpot” or “OpenJDK”). In fact, there could be an OutOfMemoryError while objects are pending in the finalizer queue, whose processing could make more memory reclaimable. There is no guaranty that finalization runs fast enough for you’re purposes. That’s why you should not rely on it.

like image 179
Holger Avatar answered Sep 28 '22 10:09

Holger


But what if this 'free' memory contains an object with finalize method? GC has to call it, but I don't see how it can even know about objects that aren't reachable anymore.

Let's say we use CMS garbage collector. After it successfully marked all live objects in a first phase, it will then scan memory again and remove all dead objects. GC thread does not call finalize method directly for these objects.

During creation, they are wrapped and added to finalizer queue by JVM (see java.lang.ref.Finalizer.register(Object)). This queue is processed in another thread (java.lang.ref.Finalizer.FinalizerThread), finalize method will be called when there are no references to the object. More details are covered in this blog post.

If so, does having finalizable objects make garbage collecting more expensive even when they are still alive?

As you can now see, most of the time it does not.

like image 38
AdamSkywalker Avatar answered Sep 28 '22 09:09

AdamSkywalker