-
CSR
-
Resolution: Approved
-
P3
-
None
-
behavioral
-
low
-
The change described in this CSR might lead some currently valid programs to throw IndexOutOfBoundException because of the stricter size check (see Solution section).
-
Java API
-
SE
Summary
Var handles obtained though the MemoryLayout API should check that the accessed segment has at least the size of the accessed root layout.
Problem
Consider the following layout:
MemoryLayout POINT =structLayout(JAVA_INT.withName("x"), JAVA_INT.withName("y"));
MemoryLayout SEQ = sequenceLayout(2, POINT);
We can use the above layout to derive a var handle which accesses the x
fields of all the structs in the sequence:
VarHandle X_HANDLE = SEQ.varHandle(PathElement.sequenceElement(), PathElement.groupElement("x"));
Let's say we have a memory segment whose size is 12. I can successfully access that segment at index 1, using the above var handle, like so:
MemorySegment segment = Arena.ofAuto().allocate(12);
int x = (int)X_HANDLE.get(segment, 0, 1); // no exception
But this seems incorrect: while access occurs withing the spatial bounds of the provided segments (after all, the x
field of the second point struct is stored from offset 8 to offset 12), such segment doesn't have enough space to fit the entire accessed sequence (as the sequence will span from offset 0 to offset 16).
Solution
The solution is to check that the accessed segment (at given base offset) has a size compatible with the size of the root layout being accessed (as opposed to checking the segment size against the accessed layout).
In the above example this is clearly not the case: the accessed segment has size 12, whereas the root layout SEQ
has size SEQ.byteSize() = 16
.
As illustrated in the above example, this behavioral change might mean that some code that is working correctly today will start throwing IndexOutOfBoundException
, as the size requirements on the accessed segment are now stricter.
Note also how this change brings the size check in sync with the alignment checks that are already performed by var handles obtained from memory layouts. That is, when we access a segment using the X_HANDLE
above, we already check that the accessed segment (at given base offset) is aligned compatibly with the root layout being accessed (as opposed to checking alignment against the accessed layout).
Moreover, in cases where today an UnsupportedOperationException
was thrown (due to atomic var handle access mode used w/o enough alignment constraints) it is possible to now get an IndexOutOfBoundException
/IllegalArgumentException
instead. This is because the implementation changes to support this CSR move the size/alignment checks on the accessed segment before the check for atomic access availability.
Finally, note that if the size of the accessed sequence is not known statically, the MemoryLayout::arrayElementVarHandle
method can still be used to obtain a var handle featuring less strict size checks, like so:
VarHandle X_UNB_HANDLE = POINT.arrayElementVarHandle(PathElement.groupElement("x"));
The above var handle can then be used to access the x
field of a point struct at a given index, where the size of the accessed sequence is only known dynamically. The var handle will only check that the accessed segment (at the offset obtained from the provided index) has a size compatible with that of the POINT
struct layout - that is, the accessed segment slice must be big enough to contain both the x
and the y
fields.
Specification
- csr of
-
JDK-8331865 Consolidate size and alignment checks in LayoutPath
- Resolved