RFR: 8289220: Locale.forLanguageTag throws NPE due to soft ref used in locale cache being cleared [v3]

John R Rose jrose at openjdk.org
Tue Jun 6 18:51:00 UTC 2023


On Tue, 6 Jun 2023 18:45:50 GMT, Erik Österlund <eosterlund at openjdk.org> wrote:

>> For hotspot, when GC occurs, it causes all threads to run to the nearest safepoint and then freeze. Generally, safepoints are generated at branch jumps, method ends(ret instructions), loops instructions, and so on. Therefore, the purpose of this patch is to make the creation and use of a softReferences in the same method without branch, jumps and loops in between, that is ensure that GC will not occur in the process of the sofeReferences be created and used.
>> 
>> That's why I didn't use `Reference.reachabilityFence(locale)`.
>
> This reasoning seems invalid. There are method calls in there, and you rely on inlining heuristics for this not to break. Please use reachabilityFence instead.

It appears you are assuming that some combination of bytecodes constitutes a  critical section that excludes the GC.  But the JVMS makes no guarantees about GC exclusion across bytecodes.

A thread can be pre-empted at any bytecode (even in the middle of a bytecode).  Another thread can trigger a GC.  Maybe the first thread will be rolled forward to a place convenient to the JVM, but you cannot predict what that will be, because the JVMS does not give you any contract about that matter.

For example, some JITs deoptimize (branch to the interpreter) at unpredictable points for reasons no Java programmer should ever think about (because it’s not in the JVMS contract).  Deoptimizing can allocate storage (for example, to materialize objects whose allocation was deferred by escape analysis).  Thus, it is not safe to assume that any particular bytecode is immune from GC.

Also, some JITs (like C2) inject synthetic safepoints injected as part of arbitrarily complex loop transformations.  A GC at such a safepoint might possibly appear to be tied to a bytecode which is simply a fall-through from a previous bytecode.  This can happen if the loop is rotated, and a fallthrough point begins to function as a back-branch in the IR.

The rule of thumb for non-JIT engineers is, if you find yourself trying to predict what how “the JIT must work”, stop.

The net of this is that, if you need to preserve an object across a critical section, don’t try to read the JIT’s mind or expect it to read yours.  Put in a reachability fence that spans that critical section.

-------------

PR Review Comment: https://git.openjdk.org/jdk/pull/14211#discussion_r1220148743


More information about the core-libs-dev mailing list