Search code examples
javaunsafe

finalize never called from the object by allocateInstance(Java)


pleaes refer to the following code, i just want to do something about unsafe.

import sun.misc.Unsafe;
import java.lang.reflect.Field;
import java.util.*;

public class A {

    public static void main(String[] args) throws Exception {
        Field f = Unsafe.class.getDeclaredField("theUnsafe");
        f.setAccessible(true);
        Unsafe u = (Unsafe) f.get(null);
        System.out.println("the while start at:" + new Date());
        long total = 0;
        while (true) {
            u.allocateInstance(B.class);
            total++;
            if (total % 100000000 == 0) {
                System.out.println(total);
                System.gc();
            }
        }
    }
}

class B {

    private int a;
    private int b;
    private double d;
    private float e;

    @Override
    protected void finalize() {
        try {
            super.finalize();
        } catch (Throwable e) {
            System.out.println("catch excep");
        }
        System.out.println("class B finalize, the a:" + a);
    }
}

the code is never oom, but the finalize of class B is never called.why? i can not find the key information....


Solution

  • This OpenJDK thread notes the following:

    Unsafe.allocateInstance() is implemented in HotSpot VM by directly calling JNI's AllocObject() function [1]. An object instance is allocated in the Java heap, but no constructors are invoked for this instance.

    Furthermore, the Java Langauge Specification (§12.6.0) specifically states that:

    The completion of an object's constructor happens-before (§17.4.5) the execution of its finalize method (in the formal sense of happens-before).

    Given that in your code you never actually call the constructors for the allocated instances, the Object.finalize() method cannot be called without first violating the aforementioned happens-before order (§17.4.5).

    Therefore, the Object.finalize() method will never be called.