Search code examples
javaoptimizationjava-8jit

JIT optimization preventing techniques


In java-8 sources we can find quite tricky way of JIT optimization inside class Class:

/*
 * Private constructor. Only the Java Virtual Machine creates Class objects.
 * This constructor is not used and prevents the default constructor being
 * generated.
 */
private Class(ClassLoader loader) {
    // Initialize final field for classLoader.  The initialization value of non-null
    // prevents future JIT optimizations from assuming this final field is null.
    classLoader = loader;
}

So, this constructor is never invoked, but JIT will be "cheated" by this trick.

My question is: could it be implemented in slightly different way, let's say

private Class() {
    classLoader = (ClassLoader)(new Object());
}

This is absolutely meaningless logic, but does it matter if constructor will never been invoked?

Would such kind of trick also prevent JIT from this optimization?


Solution

  • In Java 6 and Java 7 (and Java 8 before update 40), the constructor is as simple as private Class() {}, but in these versions, there is no classLoader field either.

    This implies that the association between Class and ClassLoader had to be maintained in a special JVM specific way, thus, getClassLoader() has to call into a native method, not necessarily involving JNI, but rather handled as a JVM intrinsic operation, but still requiring special care inside the JVM’s native code. Further, the garbage collector had to know about the special relationship.

    In contrast, hiding a field in Reflection is not so complicated, while now having an ordinary field simplifies the JVM’s native code, most notably the getClassLoader() operation and the garbage collector implementation(s). It might also be simpler for the optimizer to inline field accesses if it’s an ordinary field.


    Now, when the Class objects are created via special JVM code, not using the declared constructor, it could contradict an optimizing JIT’s assumptions made by analyzing the constructor’s actual code to predict the possible values for this final field.

    Note that nobody said that the current JIT is that smart. The comment talks about hypothetical “future JIT optimizations”. Having a constructor initializing the field with a parameter value is in line with what the JVM actually does.

    In contrast, a constructor like your suggested classLoader = (ClassLoader)(new Object()); could lead a hypothetical optimizer to conclude that this field can’t be initialized with an actual ClassLoader instance as that code can never complete normally.