Reputation: 63
Let's consider following code:
class Table {
private static int number_of_Tables=0;
public Table(){
++number_of_Tables;
}
public void finalize(){
--number_of_Tables;
}
public static int current_TableCount(){
return number_of_Tables;
}
}
What I want to achieve is that when Garbage Collector (GC) destroys the Object that the count of available Objects gets decreased by one.
But everyone here on topic of finalize()
is saying that using this method is very bad because following could happen: even though there are no references pointing to the object the GC may not destroy it immediately because GC doesn't work around the clock i.e GC will be invoked after certain amount of object are there to be destroyed i.e at certain times GC will perform the cleanup, which means that even though the object is not available anymore my counter wouldn't decrease and I would give the false information upon invoking the method curret_TableCount()
What do people do instead, to solve this kind of a problem with certainty?
There must be some kind of solution in Java?
EDIT: I need to recognize when the object is not referenced anymore i.e during runtime there exists not even one pointer(reference) to the object when this is true, i would then decrese the number of that kind of objects by one.
Upvotes: 1
Views: 1870
Reputation: 298123
…following could happen: even though there are no references pointing to the object the GC may not destroy it immediately because GC doesn't work around the clock
That’s correct. The garbage collector’s purpose is to manage memory and only to manage memory. As long as there are no memory needs, the garbage collector doesn’t need to run. It’s perfectly possible that an application runs completely without any gc cycle, when there is sufficient memory.
Further, there is no guaranty that a garbage collector run identifies all unreachable objects. It might stop its work when it identified enough reclaimable memory to allow the application to proceed.
This, however, is not the only issue. Often overlooked, the fact that the garbage collector only cares for memory needs, implies that an object may get collected even when being in use, when its memory is not needed anymore, which is possible with optimized code. This is not a theoretical issue. See for example this bug or that bug related to naive dependency on finalization, even in JDK code.
Note that even if finalize()
happens to get invoked at the right time, it’s invoked by an unspecified thread, which requires using thread safe constructs.
What do people do instead, to solve this kind of a problem with certainty?
People usually don’t have that kind of problem. If you truly manage a non-memory resource, you should use an explicit cleanup action, i.e. a method like dispose()
or close()
, to be invoked after use. The straight-forward approach is to let the class implement AutoClosable
(or a subtype of it) and use the try-with-resources statement.
Cleanup actions triggered by the garbage collector are only a last resort for dealing with scenarios where the explicit cleanup has been forgotten. As explained, implementing them needs special care.
In case of a counter maintained only for statistics, you may simply live with the fact that it is imprecise. Normally, you don’t need to know how many instances of a class exist. If you really need it, e.g. when trying to debug a memory leak, you can take a heap dump, a snapshot of all existing objects, and use a dedicated analysis tool.
Upvotes: 3