Static fields in specialized classes

Paul Sandoz paul.sandoz at oracle.com
Wed Oct 15 10:22:24 UTC 2014


On Oct 14, 2014, at 11:45 PM, Brian Goetz <brian.goetz at Oracle.COM> wrote:

>> - care might need to be taken with class initlization, static access
>> should trigger initialisation before that access occurs but does this
>> mean both Foo and Foo<int> should be initialized if access occurs
>> from the latter? (not sure if you already have this aspect covered)
> 
> I think we have this one covered.  The compiler and specializer cooperate to have this effect.
> 
> - All declarations of static members (fields and methods, including <clinit>) are stripped out during specialization.  So the static members exist only on the template (base) class.
> 
> - All references to static members (whether through classes or through instances) are rewritten to directly reference the template class.
> 
> - Specialized classes acquire a <clinit> that does "LDC template.class", idempotently forcing the template class to be initialized if it is not already.
> 

I am not sure an LDC is sufficient to guarantee initialization of the template class. See example program below.

It may be necessary to invoke UNSAFE.ensureClassInitialized after the LDC of the class.

If thats the case we could stuff a global UNSAFE instance in the constant pool when anonymously defining the class (much like direct method handles to fields).

Paul.



import sun.misc.Unsafe;

import java.lang.reflect.Field;

public class STest {

    private static final Unsafe UNSAFE;

    static {
        try {
            Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe");
            unsafeField.setAccessible(true);
            UNSAFE = (Unsafe) unsafeField.get(null);
        }
        catch (Exception e) {
            throw new AssertionError(e);
        }
    }

    static class Foo<any T> {
        static {
            System.out.println("INIT FOO");
        }

        static int x;

        T get(T t) { return t; }
    }

    static class A {
        static {
            System.out.println("INIT A");
        }

    }

    static class B {
        static {
            // This is not sufficient to initialize A
            Class<?> c = A.class;
            // Use Unsafe to ensure initialization of A
//            UNSAFE.ensureClassInitialized(c);
            System.out.println("INIT B");
        }

    }

    public static void main(String[] args) {
        System.out.printf("Should %s be initialized? %s\n", Foo.class, UNSAFE.shouldBeInitialized(Foo.class));

        System.out.println("BEFORE SPECIALIZATION");
        Foo<int> fi = new Foo<>();
        System.out.println("AFTER SPECIALIZATION");

        System.out.printf("Should %s be initialized? %s\n", Foo.class, UNSAFE.shouldBeInitialized(Foo.class));
        System.out.printf("Should %s be initialized? %s\n", fi.getClass(), UNSAFE.shouldBeInitialized(fi.getClass()));

        System.out.println("BEFORE fi.get(1)");
        System.out.println(fi.get(1));
        System.out.println("AFTER  fi.get(1)");

        System.out.println("BEFORE Foo.x");
        System.out.println(Foo.x);
        System.out.println("AFTER  Foo.x");

        B b = new B();
    }
}



More information about the valhalla-dev mailing list