On Thu, 21 May 2026 21:42:49 GMT, Vladimir Ivanov <[email protected]> wrote:
> On bytecode level booleans are represented as ints and HotSpot JVM normalizes > boolean values on memory accesses. It unconditionally applies normalization > on boolean stores, but trusts on-heap boolean locations to hold normalized > values. Normalization is applied on loads for off-heap and mismatched unsafe > accesses . > > There are 2 normalization procedures used: (1) cast int to byte and test it > against zero; and (2) truncation to least-significant bit. Truncation is > preferred (due to performance considerations), but JNI mandates testing > against zero and, historically, `#1` was used for off-heap unsafe accesses as > well. It complicated the implementation (leading to subtle bugs) and > introduced divergence in behavior at runtime (depending on execution mode and > JIT-compilation peculiarities). > > The fix uses truncation uniformly across all execution modes. It simplifies > implementation and eliminates possible divergence in behavior between > execution modes. Also, it drastically simplifies future Unsafe API > refactorings. > > There's one scenario left when it's possible to observe non-normalized > values: when mismatched access pollutes the Java heap with a bogus boolean > value, but then the value is read with a well-typed boolean access. > > Testing: hs-tier1 - hs-tier6 > > - [x] I confirm that I make this contribution in accordance with the [OpenJDK > Interim AI Policy](https://openjdk.org/legal/ai). src/hotspot/share/prims/unsafe.cpp line 232: > 230: jboolean normalize_for_read(jboolean x) { > 231: return (x & 1) != 0; > 232: } Note mild word-size issues here. Is the jboolean a byte or machine word or int32? Probably it’s 8 bits; I think all ABIs we use avoid stuffing more than 8 bits into a char. But when you try to port the `x!=0` rule to Java, you suddenly run into the issue that a value typed on the JVM stack as `byte` might in fact have nontrivial bits beyond the low eight. This confounding factor makes it nearly impossible to reason about the `x!=0` rule when executed in Java code. test/hotspot/jtreg/compiler/unsafe/UnsafeOffHeapBooleanTest.java line 46: > 44: // bytes correspond to the boolean value 'true'. > 45: UNSAFE.putShort(null, offHeapMemory, (short)0x03FF); > 46: Yep. Now we are testing for the `x&1`rule, so the test values need to change. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/31249#discussion_r3293560810 PR Review Comment: https://git.openjdk.org/jdk/pull/31249#discussion_r3293561450
