Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8320247

Some methods make promises about Java array element alignment that are too strong

XMLWordPrintable

    • Icon: CSR CSR
    • Resolution: Approved
    • Icon: P3 P3
    • 23
    • core-libs
    • None
    • behavioral
    • medium
    • Hide
      Corpus analysis has shown that these methods are rarely used, and primarily in cases that are not affected by the proposed changes. Clients depending on aligned access to heap memory, particularly with the purpose of using non-plain access modes of VarHandle will be affected. They will have to find alternatives such as using off-heap memory, or using the new FFM API together with a long[] which has stronger alignment guarantees than a byte[].
      Show
      Corpus analysis has shown that these methods are rarely used, and primarily in cases that are not affected by the proposed changes. Clients depending on aligned access to heap memory, particularly with the purpose of using non-plain access modes of VarHandle will be affected. They will have to find alternatives such as using off-heap memory, or using the new FFM API together with a long[] which has stronger alignment guarantees than a byte[].
    • Java API
    • SE

      Summary

      Change the specification and implementation of MethodHandles::byteArrayViewVarHandle, MethodHandles::byteBufferViewVarHandle, ByteBuffer::alignedSlice, and ByteBuffer::alignmentOffset to weaken the guarantees they make about the alignment of Java array elements, in order to bring them in line with the guarantees made by an arbitrary JVM implementation.

      Problem

      The JVM spec makes no guarantees about the alignment of Java array elements. At most we can assume that the elements are naturally aligned (i.e. aligned according to their size). The named methods are affected by the alignment guarantees for the elements of a byte[] which are 1-byte aligned (i.e. not aligned, really). The issue with the named methods is that they guarantee alignment when a byte[]</code> is (indirectly) accessed through another primitive type like <code class="prettyprint" >int</code> or <code class="prettyprint" >long</code> (a so-called 'mismatched access'). Given the minimal alignment guarantees of <code class="prettyprint" >byte[] elements, making any such guarantees about the alignment of accesses is incorrect, as they might not hold on all JVM implementations.

      The fact that byte[] elements can at most be assumed to be 1-byte aligned, means the start of the array elements can be located at any memory address. This memory address can also change due to a garbage collector moving the array object around (i.e. the address is unstable). Therefore, at whichever offset we access this array, the memory address of the access can also be any memory address, and is also unstable. We can not make any guarantees about the alignment of an arbitrary, unstable memory address. Therefore, we can not make any guarantees that accesses at certain offsets will be aligned (or not).

      Solution

      The proposed solution is to relax the guarantees made by the named methods, so that these methods behave consistently on all valid implementations of the JVM.

      • MethodHandles::byteArrayViewVarHandle: we can not guarantee any alignment for the accesses. Which means we can only reliably support plain get and set access modes. The javadoc text explaining which other access modes are supported, or how to compute aligned offsets into the array is dropped, as it is not guaranteed to be correct on all JVM implementations. The implementation of the returned VarHandle is changed to throw an UnsupportedOperationException for the unsupported access modes, as mandated by the spec of VarHandle (https://github.com/openjdk/jdk/blob/ffa35d8cf181cfbcb54497e997dbd18a9b62b97e/src/java.base/share/classes/java/lang/invoke/VarHandle.java#L189-L191).

      • MethodHandles::byteBufferViewVarHandle: the implementation/spec is incorrect when accessing a heap buffer (wrapping a byte[]), for the same reasons as byteArrayViewVarHandle. The spec is changed to specify that when accessing a heap buffer, only plain get and set access modes are supported. The implementation of the returned var handle is changed to throw an IllegalStateException when an access is attempted on a heap buffer using an access mode other than plain get or set. Note that we don't throw an outright UnsupportedOperationException for this case, since whether the access modes are supported depends on the byte buffer instance being used.

      • ByteBuffer::alignedSlice and ByteBuffer::alignmentOffset: The former method depends directly on the latter for all its alignment computations. We change the implementation of the latter method to throw an UnsupportedOperationException for all unit sizes greater than 1, when the buffer is non-direct.

      These decisions are also informed by similar conclusions reached in the design of the FFM API. See the existing FFM javadoc on alignment: https://download.java.net/java/early_access/jdk22/docs/api/java.base/java/lang/foreign/MemorySegment.html#segment-alignment (in particular, see the section starting with "If the segment being accessed is a heap segment, ...")

      Specification

      Specdiff: https://cr.openjdk.org/~jvernee/alignedOffset_specdiff/v3/overview-summary.html

            jvernee Jorn Vernee
            jvernee Jorn Vernee
            Paul Sandoz
            Votes:
            0 Vote for this issue
            Watchers:
            7 Start watching this issue

              Created:
              Updated:
              Resolved: