SegmentAllocator (Java SE 26 & JDK 26)
Description: declaration: module: java.base, package: java.lang.foreign, interface: SegmentAllocator
Keywords: java.lang.foreign.SegmentAllocator interface

# Interface SegmentAllocator

All Known Subinterfaces:
  `Arena`

Functional Interface:
  This is a functional interface and can therefore be used as the assignment target for a lambda expression or method reference.

@FunctionalInterface public interface SegmentAllocator
An object that may be used to allocate memory segments. Clients implementing this interface must implement the `allocate(long, long)` method. A segment allocator defines several methods which can be useful to create segments from several kinds of Java values such as primitives and arrays.

`SegmentAllocator` is a functional interface. Clients can easily obtain a new segment allocator by using either a lambda expression or a method reference:

    SegmentAllocator autoAllocator = (byteSize, byteAlignment) -> Arena.ofAuto().allocate(byteSize, byteAlignment);

This interface defines factories for commonly used allocators:

- `slicingAllocator(MemorySegment)` obtains an efficient slicing allocator, where memory is allocated by repeatedly slicing the provided memory segment;
- `prefixAllocator(MemorySegment)` obtains an allocator which wraps a segment and recycles its content upon each new allocation request.

Passing a segment allocator to an API can be especially useful in circumstances where a client wants to communicate where the results of a certain operation (performed by the API) should be stored, as a memory segment. For instance, downcall method handlesRESTRICTED can accept an additional `SegmentAllocator` parameter if the underlying foreign function is known to return a struct by-value. Effectively, the allocator parameter tells the linker where to store the return value of the foreign function.

API Note:
  Unless otherwise specified, the `allocate(long, long)` method is not thread-safe. Furthermore, memory segments allocated by a segment allocator can be associated with different lifetimes, and can even be backed by overlapping regions of memory. For these reasons, clients should generally only interact with a segment allocator they own.

  Clients should consider using an arena instead, which, provides strong thread-safety, lifetime and non-overlapping guarantees.

Since:
  22

- ## Method Summary

  Modifier and Type
  Method
  Description
  `default MemorySegment`
  `allocate(long byteSize)`
  Returns a new memory segment with the given `byteSize`.
  `MemorySegment`
  `allocate(long byteSize, long byteAlignment)`
  Returns a new memory segment with the given `byteSize` and `byteAlignment`.
  `default MemorySegment`
  `allocate(MemoryLayout layout)`
  Returns a new memory segment with the given layout.
  `default MemorySegment`
  `allocate(MemoryLayout elementLayout, long count)`
  Returns a new memory segment with the given `elementLayout` and `count`.
  `default MemorySegment`
  `allocateFrom(AddressLayout layout, MemorySegment value)`
  Returns a new memory segment initialized with the address of the provided memory segment.
  `default MemorySegment`
  `allocateFrom(ValueLayout.OfByte layout, byte value)`
  Returns a new memory segment initialized with the provided byte value.
  `default MemorySegment`
  `allocateFrom(ValueLayout.OfByte elementLayout, byte... elements)`
  Returns a new memory segment initialized with the elements in the provided byte array.
  `default MemorySegment`
  `allocateFrom(ValueLayout.OfChar layout, char value)`
  Returns a new memory segment initialized with the provided char value.
  `default MemorySegment`
  `allocateFrom(ValueLayout.OfChar elementLayout, char... elements)`
  Returns a new memory segment initialized with the elements in the provided char array.
  `default MemorySegment`
  `allocateFrom(ValueLayout.OfDouble layout, double value)`
  Returns a new memory segment initialized with the provided double value.
  `default MemorySegment`
  `allocateFrom(ValueLayout.OfDouble elementLayout, double... elements)`
  Returns a new memory segment initialized with the elements in the provided double array.
  `default MemorySegment`
  `allocateFrom(ValueLayout.OfFloat layout, float value)`
  Returns a new memory segment initialized with the provided float value.
  `default MemorySegment`
  `allocateFrom(ValueLayout.OfFloat elementLayout, float... elements)`
  Returns a new memory segment initialized with the elements in the provided float array.
  `default MemorySegment`
  `allocateFrom(ValueLayout.OfInt layout, int value)`
  Returns a new memory segment initialized with the provided int value.
  `default MemorySegment`
  `allocateFrom(ValueLayout.OfInt elementLayout, int... elements)`
  Returns a new memory segment initialized with the elements in the provided int array.
  `default MemorySegment`
  `allocateFrom(ValueLayout.OfLong layout, long value)`
  Returns a new memory segment initialized with the provided long value.
  `default MemorySegment`
  `allocateFrom(ValueLayout.OfLong elementLayout, long... elements)`
  Returns a new memory segment initialized with the elements in the provided long array.
  `default MemorySegment`
  `allocateFrom(ValueLayout.OfShort layout, short value)`
  Returns a new memory segment initialized with the provided short value.
  `default MemorySegment`
  `allocateFrom(ValueLayout.OfShort elementLayout, short... elements)`
  Returns a new memory segment initialized with the elements in the provided short array.
  `default MemorySegment`
  `allocateFrom(ValueLayout elementLayout, MemorySegment source, ValueLayout sourceElementLayout, long sourceOffset, long elementCount)`
  Returns a new memory segment initialized with the contents of the provided segment.
  `default MemorySegment`
  `allocateFrom(String str)`
  Converts a Java string into a null-terminated C string using the UTF-8 charset, storing the result into a memory segment.
  `default MemorySegment`
  `allocateFrom(String str, Charset charset)`
  Converts a Java string into a null-terminated C string using the provided charset, and storing the result into a memory segment.
  `static SegmentAllocator`
  `prefixAllocator(MemorySegment segment)`
  Returns a segment allocator that responds to allocation requests by recycling a single segment.
  `static SegmentAllocator`
  `slicingAllocator(MemorySegment segment)`
  Returns a segment allocator that responds to allocation requests by returning consecutive slices obtained from the provided segment.

- ## Method Details

  - ### allocateFrom

    default MemorySegment allocateFrom(String str)
    Converts a Java string into a null-terminated C string using the UTF-8 charset, storing the result into a memory segment.

    Calling this method is equivalent to the following code:

         allocateFrom(str, StandardCharsets.UTF_8);

    Parameters:
      `str` - the Java string to be converted into a C string
    Returns:
      a new native segment containing the converted C string

  - ### allocateFrom

    default MemorySegment allocateFrom(String str, Charset charset)
    Converts a Java string into a null-terminated C string using the provided charset, and storing the result into a memory segment.

    This method always replaces malformed-input and unmappable-character sequences with this charset's default replacement byte array. The `CharsetEncoder` class should be used when more control over the encoding process is required.

    If the given string contains any `'\0'` characters, they will be copied as well. This means that, depending on the method used to read the string, such as `MemorySegment.getString(long)`, the string will appear truncated when read again.

    Implementation Requirements:
      The default implementation for this method copies the contents of the provided Java string into a new memory segment obtained by calling `this.allocate(B + N)`, where:
      - `B` is the size, in bytes, of the string encoded using the provided charset (e.g. `str.getBytes(charset).length`);
      - `N` is the size (in bytes) of the terminator char according to the provided charset. For instance, this is 1 for `StandardCharsets.US_ASCII` and 2 for `StandardCharsets.UTF_16`.
    Parameters:
      `str` - the Java string to be converted into a C string
      `charset` - the charset used to encode the string bytes
    Returns:
      a new native segment containing the converted C string
    Throws:
      `IllegalArgumentException` - if `charset` is not a standard charset

  - ### allocateFrom

    default MemorySegment allocateFrom(ValueLayout.OfByte layout, byte value)
    Returns a new memory segment initialized with the provided byte value.

    The size of the allocated memory segment is the size of the given layout. The given value is written into the segment according to the byte order and alignment constraint of the given layout.

    Implementation Requirements:
      The default implementation is equivalent to:

           MemorySegment seg = allocate(Objects.requireNonNull(layout));
           seg.set(layout, 0, value);
           return seg;

    Parameters:
      `layout` - the layout of the block of memory to be allocated
      `value` - the value to be set in the newly allocated memory segment
    Returns:
      a new memory segment initialized with the provided byte value

  - ### allocateFrom

    default MemorySegment allocateFrom(ValueLayout.OfChar layout, char value)
    Returns a new memory segment initialized with the provided char value.

    The size of the allocated memory segment is the size of the given layout. The given value is written into the segment according to the byte order and alignment constraint of the given layout.

    Implementation Requirements:
      The default implementation is equivalent to:

           MemorySegment seg = allocate(Objects.requireNonNull(layout));
           seg.set(layout, 0, value);
           return seg;

    Parameters:
      `layout` - the layout of the block of memory to be allocated
      `value` - the value to be set in the newly allocated memory segment
    Returns:
      a new memory segment initialized with the provided char value

  - ### allocateFrom

    default MemorySegment allocateFrom(ValueLayout.OfShort layout, short value)
    Returns a new memory segment initialized with the provided short value.

    The size of the allocated memory segment is the size of the given layout. The given value is written into the segment according to the byte order and alignment constraint of the given layout.

    Implementation Requirements:
      The default implementation is equivalent to:

           MemorySegment seg = allocate(Objects.requireNonNull(layout));
           seg.set(layout, 0, value);
           return seg;

    Parameters:
      `layout` - the layout of the block of memory to be allocated
      `value` - the value to be set in the newly allocated memory segment
    Returns:
      a new memory segment initialized with the provided short value

  - ### allocateFrom

    default MemorySegment allocateFrom(ValueLayout.OfInt layout, int value)
    Returns a new memory segment initialized with the provided int value.

    The size of the allocated memory segment is the size of the given layout. The given value is written into the segment according to the byte order and alignment constraint of the given layout.

    Implementation Requirements:
      The default implementation is equivalent to:

           MemorySegment seg = allocate(Objects.requireNonNull(layout));
           seg.set(layout, 0, value);
           return seg;

    Parameters:
      `layout` - the layout of the block of memory to be allocated
      `value` - the value to be set in the newly allocated memory segment
    Returns:
      a new memory segment initialized with the provided int value

  - ### allocateFrom

    default MemorySegment allocateFrom(ValueLayout.OfFloat layout, float value)
    Returns a new memory segment initialized with the provided float value.

    The size of the allocated memory segment is the size of the given layout. The given value is written into the segment according to the byte order and alignment constraint of the given layout.

    Implementation Requirements:
      The default implementation is equivalent to:

           MemorySegment seg = allocate(Objects.requireNonNull(layout));
           seg.set(layout, 0, value);
           return seg;

    Parameters:
      `layout` - the layout of the block of memory to be allocated
      `value` - the value to be set in the newly allocated memory segment
    Returns:
      a new memory segment initialized with the provided float value

  - ### allocateFrom

    default MemorySegment allocateFrom(ValueLayout.OfLong layout, long value)
    Returns a new memory segment initialized with the provided long value.

    The size of the allocated memory segment is the size of the given layout. The given value is written into the segment according to the byte order and alignment constraint of the given layout.

    Implementation Requirements:
      The default implementation is equivalent to:

           MemorySegment seg = allocate(Objects.requireNonNull(layout));
           seg.set(layout, 0, value);
           return seg;

    Parameters:
      `layout` - the layout of the block of memory to be allocated
      `value` - the value to be set in the newly allocated memory segment
    Returns:
      a new memory segment initialized with the provided long value

  - ### allocateFrom

    default MemorySegment allocateFrom(ValueLayout.OfDouble layout, double value)
    Returns a new memory segment initialized with the provided double value.

    The size of the allocated memory segment is the size of the given layout. The given value is written into the segment according to the byte order and alignment constraint of the given layout.

    Implementation Requirements:
      The default implementation is equivalent to:

           MemorySegment seg = allocate(Objects.requireNonNull(layout));
           seg.set(layout, 0, value);
           return seg;

    Parameters:
      `layout` - the layout of the block of memory to be allocated
      `value` - the value to be set in the newly allocated memory segment
    Returns:
      a new memory segment initialized with the provided double value

  - ### allocateFrom

    default MemorySegment allocateFrom(AddressLayout layout, MemorySegment value)
    Returns a new memory segment initialized with the address of the provided memory segment.

    The address value might be narrowed according to the platform address size (see `ValueLayout.ADDRESS`).

    The size of the allocated memory segment is the size of the given layout. The given value is written into the segment according to the byte order and alignment constraint of the given layout.

    Implementation Requirements:
      The default implementation is equivalent to:

           Objects.requireNonNull(value);
           MemorySegment seg = allocate(Objects.requireNonNull(layout));
           seg.set(layout, 0, value);
           return seg;

    Parameters:
      `layout` - the layout of the block of memory to be allocated
      `value` - the value to be set in the newly allocated memory segment
    Returns:
      a new memory segment initialized with the address of the provided memory segment
    Throws:
      `IllegalArgumentException` - if `value` is not a native segment

  - ### allocateFrom

    default MemorySegment allocateFrom(ValueLayout elementLayout, MemorySegment source, ValueLayout sourceElementLayout, long sourceOffset, long elementCount)
    Returns a new memory segment initialized with the contents of the provided segment.

    The size of the allocated memory segment is the `elementLayout.byteSize() * elementCount`. The contents of the source segment is copied into the result segment element by element, according to the byte order and alignment constraint of the given element layout.

    Implementation Requirements:
      The default implementation for this method is equivalent to the following code:

          MemorySegment dest = this.allocate(elementLayout, elementCount);
          MemorySegment.copy(source, sourceElementLayout, sourceOffset, dest, elementLayout, 0, elementCount);
          return dest;

    Parameters:
      `elementLayout` - the element layout of the allocated array
      `source` - the source segment
      `sourceElementLayout` - the element layout of the source segment
      `sourceOffset` - the starting offset, in bytes, of the source segment
      `elementCount` - the number of elements in the source segment to be copied
    Returns:
      a new memory segment initialized with the contents of the provided segment
    Throws:
      `IllegalArgumentException` - if `elementLayout.byteSize() != sourceElementLayout.byteSize()`
      `IllegalArgumentException` - if the source segment/offset are incompatible with the alignment constraint in the source element layout
      `IllegalArgumentException` - if `elementLayout.byteAlignment() > elementLayout.byteSize()`
      `IllegalArgumentException` - if `sourceElementLayout.byteAlignment() > sourceElementLayout.byteSize()`
      `IllegalStateException` - if the scope associated with `source` is not alive
      `WrongThreadException` - if this method is called from a thread `T`, such that `source.isAccessibleBy(T) == false`
      `IllegalArgumentException` - if `elementCount * sourceElementLayout.byteSize()` overflows
      `IllegalArgumentException` - if `elementCount < 0`
      `IndexOutOfBoundsException` - if `sourceOffset > source.byteSize() - (elementCount * sourceElementLayout.byteSize())`
      `IndexOutOfBoundsException` - if `sourceOffset < 0`

  - ### allocateFrom

    default MemorySegment allocateFrom(ValueLayout.OfByte elementLayout, byte... elements)
    Returns a new memory segment initialized with the elements in the provided byte array.

    The size of the allocated memory segment is `elementLayout.byteSize() * elements.length`. The contents of the source array is copied into the result segment element by element, according to the byte order and alignment constraint of the given element layout.

    Implementation Requirements:
      The default implementation for this method is equivalent to the following code:

           this.allocateFrom(layout, MemorySegment.ofArray(array),
                             ValueLayout.JAVA_BYTE, 0, array.length)

    Parameters:
      `elementLayout` - the element layout of the array to be allocated
      `elements` - the byte elements to be copied to the newly allocated memory block
    Returns:
      a new memory segment initialized with the elements in the provided byte array
    Throws:
      `IllegalArgumentException` - if `elementLayout.byteAlignment() > elementLayout.byteSize()`

  - ### allocateFrom

    default MemorySegment allocateFrom(ValueLayout.OfShort elementLayout, short... elements)
    Returns a new memory segment initialized with the elements in the provided short array.

    The size of the allocated memory segment is `elementLayout.byteSize() * elements.length`. The contents of the source array are copied into the result segment element by element, according to the byte order and alignment constraint of the given element layout.

    Implementation Requirements:
      The default implementation for this method is equivalent to the following code:

           this.allocateFrom(layout, MemorySegment.ofArray(array),
                             ValueLayout.JAVA_SHORT, 0, array.length)

    Parameters:
      `elementLayout` - the element layout of the array to be allocated
      `elements` - the short elements to be copied to the newly allocated memory block
    Returns:
      a new memory segment initialized with the elements in the provided short array
    Throws:
      `IllegalArgumentException` - if `elementLayout.byteAlignment() > elementLayout.byteSize()`

  - ### allocateFrom

    default MemorySegment allocateFrom(ValueLayout.OfChar elementLayout, char... elements)
    Returns a new memory segment initialized with the elements in the provided char array.

    The size of the allocated memory segment is `elementLayout.byteSize() * elements.length`. The contents of the source array is copied into the result segment element by element, according to the byte order and alignment constraint of the given element layout.

    Implementation Requirements:
      The default implementation for this method is equivalent to the following code:

           this.allocateFrom(layout, MemorySegment.ofArray(array),
                             ValueLayout.JAVA_CHAR, 0, array.length)

    Parameters:
      `elementLayout` - the element layout of the array to be allocated
      `elements` - the char elements to be copied to the newly allocated memory block
    Returns:
      a new memory segment initialized with the elements in the provided char array
    Throws:
      `IllegalArgumentException` - if `elementLayout.byteAlignment() > elementLayout.byteSize()`

  - ### allocateFrom

    default MemorySegment allocateFrom(ValueLayout.OfInt elementLayout, int... elements)
    Returns a new memory segment initialized with the elements in the provided int array.

    The size of the allocated memory segment is `elementLayout.byteSize() * elements.length`. The contents of the source array is copied into the result segment element by element, according to the byte order and alignment constraint of the given element layout.

    Implementation Requirements:
      The default implementation for this method is equivalent to the following code:

           this.allocateFrom(layout, MemorySegment.ofArray(array),
                             ValueLayout.JAVA_INT, 0, array.length)

    Parameters:
      `elementLayout` - the element layout of the array to be allocated
      `elements` - the int elements to be copied to the newly allocated memory block
    Returns:
      a new memory segment initialized with the elements in the provided int array
    Throws:
      `IllegalArgumentException` - if `elementLayout.byteAlignment() > elementLayout.byteSize()`

  - ### allocateFrom

    default MemorySegment allocateFrom(ValueLayout.OfFloat elementLayout, float... elements)
    Returns a new memory segment initialized with the elements in the provided float array.

    The size of the allocated memory segment is `elementLayout.byteSize() * elements.length`. The contents of the source array is copied into the result segment element by element, according to the byte order and alignment constraint of the given element layout.

    Implementation Requirements:
      The default implementation for this method is equivalent to the following code:

           this.allocateFrom(layout, MemorySegment.ofArray(array),
                             ValueLayout.JAVA_FLOAT, 0, array.length)

    Parameters:
      `elementLayout` - the element layout of the array to be allocated
      `elements` - the float elements to be copied to the newly allocated memory block
    Returns:
      a new memory segment initialized with the elements in the provided float array
    Throws:
      `IllegalArgumentException` - if `elementLayout.byteAlignment() > elementLayout.byteSize()`

  - ### allocateFrom

    default MemorySegment allocateFrom(ValueLayout.OfLong elementLayout, long... elements)
    Returns a new memory segment initialized with the elements in the provided long array.

    The size of the allocated memory segment is `elementLayout.byteSize() * elements.length`. The contents of the source array is copied into the result segment element by element, according to the byte order and alignment constraint of the given element layout.

    Implementation Requirements:
      The default implementation for this method is equivalent to the following code:

           this.allocateFrom(layout, MemorySegment.ofArray(array),
                             ValueLayout.JAVA_LONG, 0, array.length)

    Parameters:
      `elementLayout` - the element layout of the array to be allocated
      `elements` - the long elements to be copied to the newly allocated memory block
    Returns:
      a new memory segment initialized with the elements in the provided long array
    Throws:
      `IllegalArgumentException` - if `elementLayout.byteAlignment() > elementLayout.byteSize()`

  - ### allocateFrom

    default MemorySegment allocateFrom(ValueLayout.OfDouble elementLayout, double... elements)
    Returns a new memory segment initialized with the elements in the provided double array.

    The size of the allocated memory segment is `elementLayout.byteSize() * elements.length`. The contents of the source array is copied into the result segment element by element, according to the byte order and alignment constraint of the given element layout.

    Implementation Requirements:
      The default implementation for this method is equivalent to the following code:

           this.allocateFrom(layout, MemorySegment.ofArray(array),
                             ValueLayout.JAVA_DOUBLE, 0, array.length)

    Parameters:
      `elementLayout` - the element layout of the array to be allocated
      `elements` - the double elements to be copied to the newly allocated memory block
    Returns:
      a new memory segment initialized with the elements in the provided double array
    Throws:
      `IllegalArgumentException` - if `elementLayout.byteAlignment() > elementLayout.byteSize()`

  - ### allocate

    default MemorySegment allocate(MemoryLayout layout)
    Returns a new memory segment with the given layout.
    Implementation Requirements:
      The default implementation for this method calls `this.allocate(layout.byteSize(), layout.byteAlignment())`.
    Parameters:
      `layout` - the layout of the block of memory to be allocated
    Returns:
      a new memory segment with the given layout

  - ### allocate

    default MemorySegment allocate(MemoryLayout elementLayout, long count)
    Returns a new memory segment with the given `elementLayout` and `count`.
    Implementation Requirements:
      The default implementation for this method calls `this.allocate(MemoryLayout.sequenceLayout(count, elementLayout))`.
    Parameters:
      `elementLayout` - the array element layout
      `count` - the array element count
    Returns:
      a new memory segment with the given `elementLayout` and `count`
    Throws:
      `IllegalArgumentException` - if `elementLayout.byteSize() * count` overflows
      `IllegalArgumentException` - if `count < 0`

  - ### allocate

    default MemorySegment allocate(long byteSize)
    Returns a new memory segment with the given `byteSize`.
    Implementation Requirements:
      The default implementation for this method calls `this.allocate(byteSize, 1)`.
    Parameters:
      `byteSize` - the size (in bytes) of the block of memory to be allocated
    Returns:
      a new memory segment with the given `byteSize`
    Throws:
      `IllegalArgumentException` - if `byteSize < 0`

  - ### allocate

    MemorySegment allocate(long byteSize, long byteAlignment)
    Returns a new memory segment with the given `byteSize` and `byteAlignment`.
    Parameters:
      `byteSize` - the size (in bytes) of the block of memory to be allocated
      `byteAlignment` - the alignment (in bytes) of the block of memory to be allocated
    Returns:
      a new memory segment with the given `byteSize` and `byteAlignment`
    Throws:
      `IllegalArgumentException` - if `byteSize < 0`, `byteAlignment <= 0`, or if `byteAlignment` is not a power of 2

  - ### slicingAllocator

    static SegmentAllocator slicingAllocator(MemorySegment segment)
    Returns a segment allocator that responds to allocation requests by returning consecutive slices obtained from the provided segment. Each new allocation request will return a new slice starting at the current offset (modulo additional padding to satisfy alignment constraint), with given size.

    The returned allocator throws `IndexOutOfBoundsException` when a slice of the provided segment with the requested size and alignment cannot be found.

    Implementation Note:
      A slicing allocator is not thread-safe.
    Parameters:
      `segment` - the segment from which the returned allocator should slice from
    Returns:
      a new slicing allocator
    Throws:
      `IllegalArgumentException` - if the `segment` is read-only

  - ### prefixAllocator

    static SegmentAllocator prefixAllocator(MemorySegment segment)
    Returns a segment allocator that responds to allocation requests by recycling a single segment. Each new allocation request will return a new slice starting at the segment offset `0`, hence the name prefix allocator.

    Equivalent to (but likely more efficient than) the following code:

        MemorySegment segment = ...
        SegmentAllocator prefixAllocator = (size, align) -> segment.asSlice(0, size, align);

    The returned allocator throws `IndexOutOfBoundsException` when a slice of the provided segment with the requested size and alignment cannot be found.
    API Note:
      A prefix allocator can be useful to limit allocation requests in case a client knows that they have fully processed the contents of the allocated segment before the subsequent allocation request takes place.
    Implementation Note:
      While a prefix allocator is thread-safe, concurrent access on the same recycling allocator might cause a thread to overwrite contents written to the underlying segment by a different thread.
    Parameters:
      `segment` - the memory segment to be recycled by the returned allocator
    Returns:
      an allocator that recycles an existing segment upon each new allocation request
    Throws:
      `IllegalArgumentException` - if the `segment` is read-only