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

Reply via email to