Possible subtle memory model error in ClassValue
David Lloyd
david.lloyd at redhat.com
Fri Aug 7 15:39:42 UTC 2020
I'm helping a colleague debug a weird problem that occurs in
ClassValue on jdk11u (and presumably on upstream as well, though it's
presently impossible to verify). As a disclaimer, the problem
manifests itself when building native images via GraalVM so it's
possible that something is simply broken there, but it seems at least
feasible that it could be a plain old Java bug so I thought I'd send
up a flare here to see if this makes sense to anyone else.
The bug itself manifests (on jdk11u) as an NPE with the following
exception trace:
java.lang.NullPointerException
at java.base/java.lang.ClassValue$ClassValueMap.loadFromCache(ClassValue.java:535)
at java.base/java.lang.ClassValue$ClassValueMap.probeHomeLocation(ClassValue.java:541)
at java.base/java.lang.ClassValue.get(ClassValue.java:101)
...
Some basic analysis shows that this should be impossible under
normal/naive circumstances: the initializer of
java.lang.ClassValue.ClassValueMap sets the corresponding field to
non-null during construction.
However, I'm wondering if this isn't a side effect of what appears to
be an incorrect double-checked lock at lines 374-378 of
ClassValue.java [1]. In order for the write to the non-volatile
`cache` field of ClassValueMap, it is my understanding that there must
be some acquire/release edge from where the variable is published to
guarantee that all of the writes are visible to the read site, and I'm
not really sure that the exit-the-constructor edge is going to match
up with with the synchronized block which protects a different
non-volatile field. And even if my feeling that this is dodgy is
valid, I'm not sure whether this NPE is a possible outcome of that
problem!
Thoughts?
[1] https://github.com/openjdk/jdk11u-dev/blob/3789983e89c9de252ef546a1b98a732a7d066650/src/java.base/share/classes/java/lang/ClassValue.java#L374-L378
--
- DML • he/him
More information about the core-libs-dev
mailing list