-
CSR
-
Resolution: Approved
-
P3
-
None
-
behavioral
-
minimal
-
The changes described in this CSR might create some incompatibilities when working with aligned layouts and heap segments. However, given all layout constants in ValueLayout are unaligned, we expect the compatibility impact to be rather small.
-
Java API
Summary
The Foreign Memory Access API should enforce alignment constraints regardless of the memory segment being accessed, regardless of whether the segment is backed by on-heap or off-heap memory.
Problem
Checking alignment constraints of on-heap segments is problematic; unlike off-heap segments, for which a concrete, physical address, can always be obtained (and checked for alignment constraints), the base address of a on-heap segment is virtualized and the alignment constraints of such virtualized address are, ultimately, implementation-dependent. The Foreign Memory Access API performs alignment checks on heap segments by simply looking at the access offset within the heap segment. However, the offset of elements in a heap array can be implementation-dependent, as it is determined by layout decisions which depend on the size of the header of an array instance. This means that it is possible for some dereference/copy operation to fail on certain platforms, but not on others. For instance, trying to read or write aligned long
values from a memory segment backed by a byte[]
array might work or not, depending on the layout of the byte[]
instance.
For more details please refer to:
https://mail.openjdk.java.net/pipermail/panama-dev/2021-November/015852.html
Solution
The solution is to introduce, for heap segments, an additional "maximum alignment" constraint - that is, the maximum alignment of addresses generated for elements of an array backing a given heap segments. This maximum alignment depends on the element type of the array backing the memory segment: for instance:
- maxAlign(byte[]) = maxAlign(boolean[]) = 1
- maxAlign(short[]) = maxAlign(char[]) = 2
- maxAlign(int[]) = maxAlign(float[]) = 4
- maxAlign(long[]) = maxAlign(double[]) = 8
Whereas, for off-heap segments we have that:
- maxAlign() = 0
Given this, we can redefine the alignment check for all memory segments as follows:
void checkAlignment(MemorySegment segment, long address, MemoryLayout layout) {
if (((address | maxAlign(segment)) % layout.byteAlignment()) != 0) {
throw new IllegalArgumentException("unaligned access!");
}
}
Note that, when access is off-heap, the above formula degenerates to the one used previously (e.g. (address % layout.byteAlignment) != 0
). However, if access is on-heap, the maximum align for the on-heap segment will effectively introduce "noise" in the alignment calculation, so that accessing elements with alignment greater than that of the element type backing the on-heap memory segments will be rejected (regardless of the platform).
Specification
Javadoc (as of December 16th, 2021): http://cr.openjdk.java.net/~mcimadamore/8278897/v1/javadoc/jdk/incubator/foreign/package-summary.html
Specdiff (as of December 16th, 2021): http://cr.openjdk.java.net/~mcimadamore/8278897/v1/specdiff_out/overview-summary.html
A specdiff of the changes (as of December 16th, 2021) is also attached to this CSR.
- csr of
-
JDK-8278897 Alignment of heap segments is not enforced correctly
-
- Resolved
-