JDK-8361935 : Clarify VarHandle set/get access on 32-bit platforms
  • Type: CSR
  • Component: core-libs
  • Sub-Component: java.lang.invoke
  • Priority: P4
  • Status: Closed
  • Resolution: Approved
  • Fix Versions: 25,26
  • Submitted: 2025-07-10
  • Updated: 2025-07-22
  • Resolved: 2025-07-22
Related Reports
CSR :  
Description
Summary
-------

Update the specification of `java.lang.invoke.MethodHandles::byteBufferViewVarHandle` to clarify a potential misconception, and update `java.lang.foreign.MemoryLayout` specification to correct a mistake.

Problem
-------

The description about aligned access for `byteBufferViewVarHandle` sounds like `get` and `set` access modes for `long` and `double` are not supported on 32-bit platforms. In reality, they are supported, but they can be non-atomic or atomic. Related documentation on `MemoryLayout` claims the problem is "word tearing", but in reality, it is non-atomic treatment of long and/or double.

 - Word tearing: More than one variables stored in one synchronization unit (word), where when updating one, the other parts of a subword region is assumed unchanged and so an update potentially overwrites changes onto other variables incorrectly
 - Non-atomic treatment of long/double: inconsistency across two words/synchronization units because you cannot synchronize them together, so reads and writes are split, and you can read a nonexistent value composed of two unrelated writes

In addition, the term "atomic"/"non-atomic" is confusing in this context: they can refer to memory access (read, write), or the whole encapsulated VH operation (CAS, CAE, etc.). We need better wording to describe the memory access without any VH operation implications.

Solution
--------

Fix the specification found in `java.lang.foreign.MemoryLayout` to state "no atomicity guarantee" instead of using "word tearing". Slightly tweak it as we do not support the `MemorySegment` type, and reuse this to `byteBufferViewVarHandle`.

Specification
-------------

```
diff --git a/src/java.base/share/classes/java/lang/foreign/MemoryLayout.java b/src/java.base/share/classes/java/lang/foreign/MemoryLayout.java
index cb51bbaf795b0..f55deba6e7fac 100644
--- a/src/java.base/share/classes/java/lang/foreign/MemoryLayout.java
+++ b/src/java.base/share/classes/java/lang/foreign/MemoryLayout.java
@@ -276,10 +276,10 @@
  * if {@code A >= S}. An aligned var handle is guaranteed to support the following
  * access modes:
  * <ul>
- * <li>read write access modes for all {@code T}. On 32-bit platforms, access modes
- *     {@code get} and {@code set} for {@code long}, {@code double} and {@code MemorySegment}
- *     are supported but might lead to word tearing, as described in Section {@jls 17.7}.
- *     of <cite>The Java Language Specification</cite>.
+ * <li>read write access modes for all {@code T}.  Access modes {@code get} and
+ *     {@code set} for {@code long}, {@code double} and {@code MemorySegment}
+ *     are supported but have no atomicity guarantee, as described in Section
+ *     {@jls 17.7} of <cite>The Java Language Specification</cite>.
  * <li>atomic update access modes for {@code int}, {@code long},
  *     {@code float}, {@code double} and {@link MemorySegment}.
  *     (Future major platform releases of the JDK may support additional
diff --git a/src/java.base/share/classes/java/lang/invoke/MethodHandles.java b/src/java.base/share/classes/java/lang/invoke/MethodHandles.java
index 3d7ba22e54e09..b0f7a53ea713a 100644
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandles.java
+++ b/src/java.base/share/classes/java/lang/invoke/MethodHandles.java
@@ -4305,9 +4305,10 @@ public static VarHandle byteArrayViewVarHandle(Class<?> viewArrayClass,
      * If access is aligned then following access modes are supported and are
      * guaranteed to support atomic access:
      * <ul>
-     * <li>read write access modes for all {@code T}, with the exception of
-     *     access modes {@code get} and {@code set} for {@code long} and
-     *     {@code double} on 32-bit platforms.
+     * <li>read write access modes for all {@code T}.  Access modes {@code get}
+     *     and {@code set} for {@code long} and {@code double} are supported but
+     *     have no atomicity guarantee, as described in Section {@jls 17.7} of
+     *     <cite>The Java Language Specification</cite>.
      * <li>atomic update access modes for {@code int}, {@code long},
      *     {@code float} or {@code double}.
      *     (Future major platform releases of the JDK may support additional
```
Comments
Moving revised request back to Approved.
22-07-2025

I updated this again after consulting [~mcimadamore] and [~jvernee], avoiding the term "atomic" or "non-atomic" that is ambiguous (for VH operation vs the underlying memory access). The updated specs simply state "make no atomicity guarantee", and additionally removed the 32-bit restriction (as the JLS does not have this precondition too)
17-07-2025

Moving to Approved.
15-07-2025

Re-finalizing with Paul's approval.
15-07-2025

We don't qualify the read/write access modes as atomic because they are generally considered so (unless edge cases are explicitly called out). We explicitly qualify the read-modify-write (update) access modes as atomic because they are composed of read/write operations (sometimes explicitly so e.g., CAS on byte when no hardware support). In that respect I think the updated description to MemoryLayout is ok and is aligned with documentation on VarHandle.
14-07-2025

Moving to Provisional, not Approved. [~psandoz], please re-affirm your approval of the current wording.
14-07-2025

Another term we can consider is "loosely consistent" as used for large valhalla values that have similar separate-update semantics. However that term is not final.
14-07-2025

In the past we have used "word tearing" to indicate within (intra) and between (inter) memory effects, whereas from the JLS perspective it is about interactions between fields/elements. IMO word tearing is a very confusing term and it is best to stick to using it as in section 17.6 of the JLS.
14-07-2025

I re-read the context. In `MethodHandles` the spec in question includes "support atomic access" so "non-atomic" should be fine. "atomic" is not mentioned in `MemoryLayout`, but since we link to the JLS I think this term "non-atomic" is well-defined in the context too.
14-07-2025

I used the term word tearing in memory layout javadoc deliberately -- because this section of the javadoc uses the word "atomic" in two ways. One, to explain under which conditions CAS-like operations (which are denoted as "atomic" both here and in the original var handle specification). E.g. "atomic update access modes for {@code int}, {@code long} ..." Since we're using atomic for that purpose, I think using non-atomic when we really mean "torn" is too confusing. For this reason I referred to the term "word tearing" to describe what happens when you read a long/double on 32-bits. So, I think that either we keep use the word "tearing", or we find some other term to replace the uses of atomic in both javadocs (otherwise the problem I tried to solve is still there).
14-07-2025

Adding 25 to fix version; intended to backport.
11-07-2025