Discussions of finalizable objects in Java typically discuss the common indirect costs that happen when finalizable objects (and their associated resources) cannot be quickly garbage collected.
I'm more interested, at the moment, in what the actual direct cost of being finalizable is, both in memory terms, and in object allocation time. I've seen oblique references to the existence of such a cost in a number of places, for example, Oracle's article on finalization memory retention issues notes:
When
obj
is allocated, the JVM internally records thatobj
is finalizable. This typically slows down the otherwise fast allocation path that modern JVMs have.
How does the JVM record that an object instance is finalizable, and what are the memory and performance costs of doing so?
For those interested in my specific application:
We produce and retain millions of incredibly lightweight objects; adding a single pointer to these objects is incredibly costly, so we've done a fair bit of work to remove pointers from them, instead using smaller numeric ids packed into a subset of the bits of a field. Unpacking the number allows the shared immutable property with that id to be retrieved from a Pool that stores them using a Map.
The remaining question is how to handle the garbage collection of property values that are no longer used.
One strategy that has been considered is using reference counting; when objects are created and retrieve the pooled id for a value, the reference count for that value is incremented; when it is no longer used, it must be decremented.
One option to ensure this decrement happens is to add the following finalize method:
public void finalize() {
Pool.release(getPropertyId());
}
However, if the very act of being finalizable means that an additional pointer to the object must be kept, the up-front cost of being finalizable would be considered high for this application. If it means additional objects must be allocated, it would almost certainly be too high...hence, my question: what is the direct up-front cost of being finalizable?
finalize()
will be called - or? – Membranousn
weak or transient reference objects if there aren
objects to do cleanup for, and the JVM must take notes on each such weak reference so they can be enqueued when the corresponding object is garbage collected. – DoilyWeakReference
, so you don't have any extra objects. But even so, that extra information is generally considered significantly cheaper than finalization. – Outputjava.lang.ref.Reference
(FinalReference), so they can't be cheaper, but their behavior is more complicated. Moreover, HotSpot JVM does not inline allocation of objects that have a non-trivial finalizer. – Perfectible