class A extends B
{
 C ob1=new C();
 D ob2=new D();
 protected void finalize()
 {
  System.out.println("Finalizing A");
  super.finalize();
 }
 public static void main(String ss[])
 {
  new A();
  System.gc();
 }
}

Though System,gc() doesn't guarantee the running of finalization, my question is if the JVM is able to run the finalizations at the time of call to gc(), what will be the order of execution of the finalizations for the classes A,B,C,D (assuming that all have finalizations with a code similar to that of A's and that apart from A, none of the classes explicitly inherit).

Dani AI

Generated

Short answer: the JVM does not guarantee any particular order for finalizer invocation. The output you saw (Finalizing D, Finalizing C, Finalizing A, Finalizing B) is a perfectly plausible outcome, but another run, another GC algorithm, or another JVM may invoke those finalizers in a different order or even concurrently. (docs.oracle.com)

Why B runs after A in your trace: finalize calls for a single object are performed by the object’s overridden method, and superclass finalization is not automatic — the subclass must explicitly call super.finalize() (and the common pattern is to do that in a finally block). That is why A’s code can cause B’s finalizer to run after A’s own cleanup. Also, finalize() is guaranteed to run at most once per object and exceptions during finalization stop that object’s finalization chain. (docs.oracle.com)

Why C and D might run before A: C and D are separate objects (composition), so when A becomes unreachable the GC often discovers the whole unreachable graph (A, C, D) at once. The GC may schedule finalizers for any or all of those objects independently, possibly on different threads, so a field object’s finalizer can run before the container’s finalizer. There isn’t a separate “base object” in memory; inheritance fields are part of the same instance, and superclass finalization happens via the explicit super.finalize() call in the instance’s finalize chain. (docs.oracle.com)

Practical advice: don’t rely on finalize() for cleanup. Finalization has been deprecated for removal and is unreliable for timely resource release. Prefer explicit close/AutoCloseable with try-with-resources, or register post‑mortem cleanup with java.lang.ref.Cleaner when you need an automatic safety net. If you must observe finalizer behavior for debugging, run many iterations, try different GC implementations and options, and remember --finalization=disabled / JEP 421 exists for testing. (openjdk.org)

Notes tied to the thread: , your experiment is useful (as suggested) to observe one possible ordering; correctly pointed to the language rules — those rules are why you should not assume a stable ordering in production code.

Recommended Answers

All 9 Replies

For questions that ask: "What will happen if ..." I recommend you write a program, execute it, look at the output and see happened.

For questions that ask: "What will happen if ..." I recommend you write a program, execute it, look at the output and see happened.

My question, essentially, was that is any order guaranteed ? If I run the program and get an output, it may be not true in every other case. I mean, does documentation for such a thing exists ?

When I ran the program, I got the output :

Finalizing D
Finalizing C
Finalizing A
Finalizing B

I understand that B's finalize() will be called after A's because B is a superclass of A and is called after printing A's finalization message. But when garbage collection occurs, it will see C,D and A's objects without a reference (B's object will be also visible or not ?). But why will it decide to call the finalize() of D and C (and why D before C) before A ?

> But why will it decide to call the finalize() of D and C before A ?

AFAICT, as per the specification, the Java programming language makes no guarantee regarding the order in which finalize method is called on the "finalize eligible" objects.

Thanks. Just one more thing. Since the finalize() of the base class is not called until the derived class calls it (super.finalize()), does it mean that JVM is not aware of the existence of an object of the base class (which is constructed whenever a derived class object is formed.

The way I see it, there is no such thing as the "base object" in memory. For the given code snippet, there are only 3 custom object instances in memory. One of type B, C and D each; no A instance.

public class MemTest {
    public static void main(String[] args) {
        D d = new D();
        d.doIt();
    }
}

class A {}

class B {}

class C {}

class D extends A {    
    private C c;    
    private B b;    
    public D() {
        super();
        c = new C();
        b = new B();
    }    
    public void doIt() {
        System.out.println("HI");
    }
}

If you don't call `super.finalize()` inside the overridden `finalize` method of your subclass, the finalization of your subclass instance would complete and the space will be reclaimed *without* the finalize of the super class be invoked. This might be undesirable in cases where the `finalize` method of the super class is responsible for releasing scarce resources held by it (e.g. file handles).

Thanks.

The way I see it, there is no such thing as the "base object" in memory.

But, whenever derived class object is created, memory is assigned to base class members too, and we can access the base class fields using super. Isn't super a reference to the base class object.

> But, whenever derived class object is created, memory is assigned to base class
> members too

Yes, memory is assigned for all those member variables of the base class but there is no *separate* base class object created. The fields and methods which can be inherited are *inherited*. When you extend an existing class, you end up with a class which has everything that the super class has along with the members/methods declared for your new class. AFAICT, the concept of super classes is just a logical abstraction language designers have come up with to facilitate re-use, polymorphism etc. Also, why should an object of class A be created when I have specifically asked the runtime to create an object of class D?

> we can access the base class fields using super. Isn't super a reference to the
> base class object

A quick quiz; what does the following snippet print:

package gone.to.heaven;
class MyClass {
  public static void main(final String[] args) {
    MyClass c = new MyClass();
    System.out.println(c.superToString());
    System.out.println(c.toString());
  }
  public String superToString() {
    return super.toString();
  }
}

In case you were wondering, it prints the same thing both the times which is gone.to.heaven.MyClass@123456 .

Another quick quiz; does the following piece of code compile?

class MyClass {
  public void doSomething() {
    Object obj = super;
  }
}

No, it doesn't, because there is *no* `super` object which can be assigned to `obj`. `super` is a language feature/abstraction which allows you to access the immediate superclass methods/members.

Of course, I would be more than happy to be directed at resources which say otherwise. :-)

Thanks again. I also tried to explicitly inherit a class and execute

super.toString()

. That also displayed just the derived class' object info. So that about does it.

Thanks again.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.