1

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.

4

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.

| improve this answer | |
  • See the edit the OP made to their question 23 hours ago, and my response in the comments below the OP. – Robert Harvey Nov 25 '19 at 16:25
  • @RobertHarvey Doesn't seem helpful. – JimmyJames Nov 25 '19 at 17:28
  • Well, the description the OP provided describes a collection. Granted, the description is rather abstract. – Robert Harvey Nov 25 '19 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. – JimmyJames Nov 25 '19 at 17:42
  • Isn't an ordinary collection one of the alternatives? – Robert Harvey Nov 25 '19 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.

| improve this answer | |
  • Probably ought to have a tryfinally in there, otherwise you might end up with unreleased resources if the user code throws an exception. – Ilmari Karonen Nov 26 '19 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. – Kasper van den Berg Nov 26 '19 at 12:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.