SpringBootVersion 2.5.0-RC1 spring-petclinic-3.0.0 tomcat-10.1.5

It can happen that static method javax.el.Jre9Compat.isSupported() is called before static initialization block of Jre9Compat is executed. This issue becomes apparent because the compilation graph of certain methods that utilize these classes may vary. Specifically, within the javax.el.ImportHandler.findClass(String, boolean) method, there is a condition !jreCompat.isExported(clazz), and in case jreCompact isinstanceOf JreCompat, this condition always returns false leading to the possibility of constant folding for this method. In case that jreCompat isinstanceOf Jre9Compat it can be both true and false, resulting in different compilation outcomes. This leads to non-deterministic GraalVM NI builds, but also leads to non-deterministic JRE platform support.

Below is little snippet of code that proves the behavior.

class JreCompat {
    static final JreCompat instance;

    static {
        if (Jre9Compat.isSupported()) {
            instance = new Jre9Compat();
        } else {
            instance = new JreCompat();
        }
    }

    public static JreCompat getInstance() {
        return instance;
    }
}

class Jre9Compat extends JreCompat {

    final static Object obj;

    static {
        obj = new Object();
    }

    static boolean isSupported() {
        return obj != null;
    }

}


public final class HelloWorld {
    public static void main(String[] args) {
        System.out.println(Jre9Compat.isSupported());
        System.out.println(JreCompat.getInstance().getClass());
    }
}

After running this code snippet output is: true JreCompat.java. But after commenting first line in main method output is: Jre9Compat.java.

This should be easy to solv by calling JreCompat.getInstance()very early, before anyone else calls Jre9Compat.isSupported().

Comment From: wilkinsona

Thanks for the suggestions but the behaviour and implementation of the EL API is out of our control. You may want to suggest some changes to the maintainers of javax.el.JreCompat and javax.el.Jre9Compat.

Comment From: cstancu

While this is a problem in a dependency it seems that the non-deterministic behavior around JreCompat could also lead to serious, hard to debug issues in Spring.