5

I have a Java 11 project involving multiple classes. In the present scenario, 2 of my classes - A and B - implement the java finalize() method, which is now deprecated for good. I understand the method may not be removed in the near future but I think it best to find a replacement for finalize right away.

finalize() in class A is mainly focused destroying an object of long type which is a protected member variable and on printing certain messages to log. finalize() in class B simply prints certain messages to log.

Instances of class A are created from several other classes and class B extends another class ClassLoader. (Code snippets included below.)

I went through quite a few suggestions such as,

These are explained not so well in the first place and even when they are, the examples are specific to single class projects with the main method present in the same class. I'm unable to move forward with the minimal solution that I found online.

Post my research, Autocloseable with try-with-resources seems to be my best option. I understand that my classes A and B should implement Autocloseable while the callees (A bit unsure here) should use try-with-resources.

I will be grateful for any help towards simplifying this problem even if it is to fill the gaps that may be present in my understanding of the scenario.

A.java

class A
{
    protected long a_var;
    protected A(String stmt, boolean isd)
    {
        // a_var is initialized here
    }

    public void finalize()
    {
        if(a_var != 0)
        {
            log("CALL destroy !");
            destroy(a_var);
            log("DONE destroy !");
        }
    }
}

B.java

public class B extends extends ClassLoader
{
    protected void finalize ()
    {
        log("No action");
    }
}
Joachim Sauer
  • 302,674
  • 57
  • 556
  • 614
userAsh
  • 147
  • 10
  • 1
    Well `B.finalize()` already does nothing except log itself, and you will hardly miss extraneous log messages: and it is already invalid, as it should call `super.finalize()` in its (missing) `finally` block; so you can simply remove it with 100% equanimity. *But* if `C.finalize()` exists it will now be called for instances of `B`, which might prove interesting. `A.finalize()` calls `A.destroy()`, which you haven't provided, so it is impossible to comment further. – user207421 Sep 18 '19 at 10:36
  • 2
    A **WeakReference** (or possibly **SoftReference**) spring to mind. If the objects are in an Object/Relational mapping, it can be done in the (JPA) container. – Joop Eggen Sep 18 '19 at 10:43
  • Thank you, user207421. Please note that Class B extends ClassLoader. I have made the edit as required in my query description above. Let's say I need to retain all functionality currently part of the finalize methods, how would I take the next step? – userAsh Sep 18 '19 at 11:01
  • 1
    `B` extended class `C` in the original question, as per my comment. But as `java.lang.ClassLoader` doesn't implement `finalize()` you don't have to worry about removing `B.finalize()` at all, as I have already stated. – user207421 Sep 18 '19 at 11:10
  • If I remove B.finalize(), wouldn't the log message be lost? Although the message I have provided in the question is "No action", it isn't exactly so in the project and it is necessary that I retain it. Am I missing something here? – userAsh Sep 18 '19 at 11:18
  • Yes, I already said that. and I also already said that you shouldn't miss it, as it is logged any old time or maybe never. It is necessary that you retain it why? – user207421 Sep 18 '19 at 11:26
  • 3
    `java.lang.ref.Cleaner` (or its underlying technology the `PhantomReference`) is yet another way to replace `finalize()` and probably the most straightforward replacement. – Joachim Sauer Sep 18 '19 at 11:30

1 Answers1

3

So, the AutoCloseable interface with try-with-resources seems to be your best option by far. This alternative for finalize is, according to me, the simplest to implement - but this may of course vary depending on the complexity of each project.

class A must implement AutoCloseable class A implements AutoCloseable and all places where it's object is created should be enclosed in a try like try (A obj = new A())

Now go further and override the close method provided by AutoCloseable and make a call to destroy() from within.

class A implements AutoCloseable
{
    @Override
    public void close()
    {
        //log messages
        destroy();
    }
}

class X
{
    // suppose creating object of A within some method
    // enclose in try
    try ( A obj = new A ())
    {
        //use obj
    }
    // at the end of scope, the close() method of A will be called.
}
aashima
  • 1,203
  • 12
  • 31