All the shared secrets are injected as a side effect of loading the
class the getter ensures is initialized - which should provide the
necessary constraints to ensure there is no way for a reordering to
happen where the access object returned can be observed to be null.
E.g.
if (javaSecuritySignatureAccess == null) {
ensureClassInitialized(Signature.class);
}
return javaSecuritySignatureAccess;
Signature.java:
static {
SharedSecrets.setJavaSecuritySignatureAccess(...);
}
/Claes
On 2020-12-29 14:55, Johannes Kuhn wrote:
Depends on what `initialize()` is.
If it (at least) reads a volatile field, then the compiler can't reorder
the second read before the first.
- Johannes
On 29-Dec-20 14:42, some-java-user-99206970363698485...@vodafonemail.de
wrote:
Hello,
the class `jdk.internal.access.SharedSecrets` provides getter methods
which all look similar to this:
```
if (static_field == null) {
initialize();
}
return static_field;
```
However, neither the static fields are `volatile` nor are the getter
methods synchronized. So if my
understanding of the Java Memory Model is correct, the compiler is
free to reorder the two static
field reads. So it is in theory possible that the first read yields a
non-`null` value, but the
second read yields a `null` value which leads to incorrect behavior
(for further reading [1]).
It is probably rather unlikely that this actually happens because
`SharedSecrets` is in most cases
accessed from static initializers (which are only run once) and
because not many classes access the
same `SharedSecrets` fields.
Is this analysis correct or did I forget to consider parts of the
Memory Model logic, or is there
some JVM magic I am missing?
Kind regards
[1]
https://shipilev.net/blog/2016/close-encounters-of-jmm-kind/#wishful-benign-is-resilient