4

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 achive is that when GarbegeCollector (GC) destroys the Object that the count of available Objects gets decresed 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?

EDIT2: 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.

asked Nov 24, 2019 at 16:11
11
  • 1
    At least related (if not a dupe): softwareengineering.stackexchange.com/questions/333146/… Commented Nov 24, 2019 at 16:23
  • 4
    Change your question so that it asks about the actual problem you are trying to solve, instead of the method you have chosen to solve it (use your approach only to demonstrate your attempt to solve the problem). See meta.stackexchange.com/a/66378 Commented Nov 24, 2019 at 16:26
  • 3
    When an Object is not available to the user anymore that the Programm gives the accurate Information to the user about the number of available Items. For example an item that is bought from a store how many items of the same kind are still in the store -- Use a collection. Collections are designed specifically to do this. Commented Nov 25, 2019 at 16:23
  • 1
    Why would you be asked to re-invent the Java garbage collector, poorly? Commented Nov 26, 2019 at 5:12
  • 1
    Have a look here: geeksforgeeks.org/object-pool-design-pattern Commented Nov 26, 2019 at 5:12

2 Answers 2

6

Depending on your design there are two mechanisms in Java that you can use instead. finalize is to be avoided mainly because it creates performance issues with garbage collection and it possible create new references to the object that is being collected leading to undefined behavior i.e. big problems.

References

ReferenceQueue

If you want to be informed of the collection of an object in Java, the safe way to do that is to use a Reference and register it with a ReferenceQueue. This can be a little confusing to work with because you need to make sure it's the reference that tells you what object was removed, the a reference to actual object that is was collected will not be passed to you. This is to avoid the problem mentioned above with finalize.

WeakHashMap

A similar but perhaps simpler approach to using a Reference for this is to use a 'weak' Map such as WeakHashMap. You can periodically check the Map for what remains and by elimination determine what has been removed.

Potential problem with References

The issue with this in your case is that the object will not be collected immediately after you release all references to it. In fact it may never be collected at all. One scenario could be where you have a small number of medium-to-long-lived objects (including this one) that end up in a tenured generation but everything else is short-lived. The tenured generation never fills up and therefore never gets collected so even if the garbage collector runs, some of your table objects may not be collected.

The upshot is that if you need immediate and/or deterministic counting, you can't rely on garbage collection.

Closeable or AutoCloseable

Another option is to implement the Closeable or AutoCloseable interface. This makes your class available for use in a 'try-with' block like so:

try (Table table = new Table()) {
 /* Do things with table */
}

When the block exits (for any reason) the close method on Table will be executed. This is probably the best possible option if tables exist within the scope of a method. If you are holding these in a structure that lives on the heap and they outlive the method in which they are defined, this won't work for you.

Explicit management

The last option you have is to explicitly call a method when you are no longer using the object.

Pools

A pool allows you to keep track of set of objects. The challenge is that you need to make sure each object get's released from the client-side. If you've ever used a connection pool with database connections, you should know that you need to call close when every you are done using a connection. If you don't, you will end up with a connection leak and the pool can eventually run out of available connections.

Inverted Control

One option I've used to put all the resource management in one place. To give an example of this Consider again the Connection pool example. The common way to use them is to have code all of over the application that requests a Connection and then when it's done, close will be called. This is fine if you use try-with blocks or otherwise guarantee it's being called at the right time. You can avoid the need to do that however with something like this:

class QueryExecutor {
 public void execute(SqlQuery query, ResultSetHandler handler) {
 try (Connection conn = pool.getConnection()) {
 try (Statement stmt = conn.createStatement()) {
 try (ResultSet rs = stmt.executeQuery(query.toString())) {
 handler.process(rs);
 }
 }
 }
 }
}

The advantage here (aside from DRY) is that you have one place to make sure all of this is being done correctly instead of having to worry about all the possible places where a close might have been missed.

answered Nov 25, 2019 at 15:45
8
  • See the edit the OP made to their question 23 hours ago, and my response in the comments below the OP. Commented Nov 25, 2019 at 16:25
  • @RobertHarvey Doesn't seem helpful. Commented Nov 25, 2019 at 17:28
  • Well, the description the OP provided describes a collection. Granted, the description is rather abstract. Commented Nov 25, 2019 at 17:39
  • 1
    @RobertHarvey I get where you are going but the attempt to use finalize() for counting objects or other purposes, anything at all really, is a pretty disastrous approach in Java. It's also somewhat unfortunately common especially for people coming from a C++ background. I think a description of the alternatives is useful even if that's not what the OP really needs. Commented Nov 25, 2019 at 17:42
  • Isn't an ordinary collection one of the alternatives? Commented Nov 25, 2019 at 19:03
3

Instead of relying on the gc to call finalize(), a manual 'convention' of calling close(), or something similar to C#'s language supported using and Dispose() (which is still a convention requiring manual use of the pattern) you can use a procedure which accepts a single method interface (or C# delegate) and calls its method with the resource to manage (or object to count):

interface IFrobstinatorUser<T>
{
 T use(Frobstinator toUse);
}
class FrobstinatorProvider
{
 public T withFrobstinatorDo<T>(IFrobstinatorUser<T> client)
 {
 // Do everything required before a Frobstinator can be used.
 // For example: incrementing the count of Frobstinators that are in use.
 try
 {
 Frobstinator item = new Frobstinator();
 T result = client.use(item);
 // If needed, we can do something here with item after client is done use it and returns normally
 return result;
 }
 finally
 {
 // We can rely on control always returning here afterclient.use(); it is safer than convention based mechanisms.
 // At this point we can do whatever we want or is needed.
 // Such as releasing resources and decrementing a count of Frobstinators in use.
 }
 }
}

Use:

Oelong mifftibleOelong()
{
 Oelong oelongToMifftible = new Oelong();
 FrobstinatorProvider provider = repo.giveFrobstinatorProvider();
 return provider.withFrobstinatorDo(
 new IFrobstinatorUser<Oelong> {
 Oelong use(Frobstinator item) {
 return item.mifftible(oelongToMifftible);
 }
 });
}

'Frobstinator', 'Oelong', and 'mifftible' are made-up words standing for a service, object, and action respectively.

The advantage of using a procedure (method) that calls a callback with the resource, the callback needs to use, is that control almost always returns to the stamenent after the callback; giving us the opportiunity to always do something when the resource is no longer used.

answered Nov 24, 2019 at 21:27
2
  • Probably ought to have a try ... finally in there, otherwise you might end up with unreleased resources if the user code throws an exception. Commented Nov 26, 2019 at 10:57
  • Most often yes. However the scheme gives you complete freedom to handle resources and exceptions any way you want in withFrobstinatorDo(). Updated answer to clarify though; thank for the heads up. Commented Nov 26, 2019 at 12:16

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.