Allocating arrays into memory segments – Foreign (Function) Memory API

Java Certification Exams and ProgrammingCopying and slicing memory segments, Exams of Java, Java Exams Allocating arrays into memory segments – Foreign (Function) Memory API
0 Comments

143. Allocating arrays into memory segments

Now that we know how to create memory segments for storing single values let’s make a step further and let’s try to store an array of integers. For instance, let’s define a memory segment for storing the following array: [11, 21, 12, 7, 33, 1, 3, 6].A Java int needs 4 bytes (32 bits) and we have 8 integers, so we need a memory segment of 4 bytes x 8 = 32 bytes = 256 bits. If we try to represent this memory segment then we can do it as in the following figure:

Figure 7.9 – A memory segment of 8 integers

In code lines, we can allocate this memory segment via any of the following approaches (arena is an instance of Arena):

MemorySegment segment = MemorySegment
  .allocateNative(32, arena.scope());
MemorySegment segment = MemorySegment
  .allocateNative(4 * 8, arena.scope());
MemorySegment segment = MemorySegment.allocateNative(
  ValueLayout.JAVA_INT.byteSize() * 8, arena.scope());
MemorySegment segment = MemorySegment
  .allocateNative(Integer.SIZE/8 * 8, arena.scope());
MemorySegment segment = MemorySegment
  .allocateNative(Integer.BYTES * 8, arena.scope());

Next, we can use the set(OfInt layout, long offset, int value) method for populating the memory segment as follows:

segment.set(ValueLayout.JAVA_INT, 0, 11);
segment.set(ValueLayout.JAVA_INT, 4, 21);
segment.set(ValueLayout.JAVA_INT, 8, 12);
segment.set(ValueLayout.JAVA_INT, 12, 7);
segment.set(ValueLayout.JAVA_INT, 16, 33);
segment.set(ValueLayout.JAVA_INT, 20, 1);
segment.set(ValueLayout.JAVA_INT, 24, 3);
segment.set(ValueLayout.JAVA_INT, 28, 6);

Or, we can use the setAtIndex(OfInt layout, long index, int value) method as follows:

segment.setAtIndex(ValueLayout.JAVA_INT, 0, 11);
segment.setAtIndex(ValueLayout.JAVA_INT, 1, 21);
segment.setAtIndex(ValueLayout.JAVA_INT, 2, 12);
segment.setAtIndex(ValueLayout.JAVA_INT, 3, 7);
segment.setAtIndex(ValueLayout.JAVA_INT, 4, 33);
segment.setAtIndex(ValueLayout.JAVA_INT, 5, 1);
segment.setAtIndex(ValueLayout.JAVA_INT, 6, 3);
segment.setAtIndex(ValueLayout.JAVA_INT, 7, 6);

We already know that we can access any of these integers via get() using the offset or via getAtIndex() using the index. This time, let’s try to use this memory segment to populate an IntVector (introduced in Chapter 5). The code should look as follows:

IntVector v = IntVector.fromMemorySegment(
  VS256, segment, 0, ByteOrder.nativeOrder());

So, the Vector API exposes the fromMemorySegment() method, especially for populating a vector from a memory segment. The ByteOrder can be nativeOrder(), which means the platform’s native order of bytes, or BIG_ENDIAN (big-endian byte order), or LITTLE_ORDER (little-endian byte order).A more convenient approach for populating the memory segment relies on a suite of Arena.allocateArray() methods. These methods create and populate the memory segment in a single line of code as follows:

MemorySegment segment = arena.allocateArray(
  ValueLayout.JAVA_INT, 11, 21, 12, 7, 33, 1, 3, 6);
// or, like this
MemorySegment segment = arena.allocateArray(
  ValueLayout.JAVA_INT,
  new int[]{11, 21, 12, 7,  33, 1, 3,  6});

Or, here it is a char[] array:

MemorySegment segment = arena.allocateArray(
  ValueLayout.JAVA_CHAR, “abcd”.toCharArray());

All these examples allocate an off-heap memory segment. If we need an on-heap memory segment then we can rely on MemorySegment.ofArray() as follows:

MemorySegment segment = MemorySegment
  .ofArray(new int[]{11, 21, 12, 7, 33, 1, 3, 6});

For complete examples, please consider the bundled code.


Leave a Reply

Your email address will not be published. Required fields are marked *