apache/flink · error · IllegalStateException

Memory segment does not represent off heap memory

Error message

Memory segment does not represent off heap memory

What it means

MemorySegment.getAddress() returns the absolute native memory address, which is only meaningful for off-heap segments; it throws IllegalStateException('Memory segment does not represent off heap memory') when heapMemory != null. For heap segments the 'address' field is an offset into the heap array (unsafe machinery), not a real pointer.

Source

Thrown at flink-core/src/main/java/org/apache/flink/core/memory/MemorySegment.java:306

    public ByteBuffer getOffHeapBuffer() {
        if (offHeapBuffer != null) {
            return offHeapBuffer;
        } else {
            throw new IllegalStateException("Memory segment does not represent off-heap buffer");
        }
    }

    /**
     * Returns the memory address of off-heap memory segments.
     *
     * @return absolute memory address outside the heap
     * @throws IllegalStateException if the memory segment does not represent off-heap memory
     */
    public long getAddress() {
        if (heapMemory == null) {
            return address;
        } else {
            throw new IllegalStateException("Memory segment does not represent off heap memory");
        }
    }

    /**
     * Wraps the chunk of the underlying memory located between <tt>offset</tt> and <tt>offset +
     * length</tt> in a NIO ByteBuffer. The ByteBuffer has the full segment as capacity and the
     * offset and length parameters set the buffers position and limit.
     *
     * @param offset The offset in the memory segment.
     * @param length The number of bytes to be wrapped as a buffer.
     * @return A <tt>ByteBuffer</tt> backed by the specified portion of the memory segment.
     * @throws IndexOutOfBoundsException Thrown, if offset is negative or larger than the memory
     *     segment size, or if the offset plus the length is larger than the segment size.
     */
    public ByteBuffer wrap(int offset, int length) {
        if (!allowWrap) {
            throw new UnsupportedOperationException(
                    "Wrap is not supported by this segment. This usually indicates that the underlying memory is unsafe, thus transferring of ownership is not allowed.");

View on GitHub (pinned to 2f3c205e92)

Solutions

  1. Restrict getAddress() usage to segments where segment.isOffHeap() is true; for heap segments use getArray() plus sun.misc.Unsafe BYTE_ARRAY_BASE_OFFSET instead.
  2. Prefer the segment's own copy/compare/swap methods (copyTo, copyFromUnsafe, compare, swapBytes) which handle both backings, removing the need for raw addresses.
  3. If a long pointer is genuinely required, ensure the segment is allocated off-heap via MemorySegmentFactory.allocateOffHeapMemory.

Example fix

// before
long ptr = segment.getAddress() + offset; // IllegalStateException on heap segment

// after
long ptr = segment.isOffHeap()
        ? segment.getAddress() + offset
        : Unsafe.ARRAY_BYTE_BASE_OFFSET + offset; // combined with segment.getArray() as unsafe base
Defensive patterns

Strategy: validation

Validate before calling

if (segment.isOffHeap()) {
    long ptr = segment.getAddress() + offset;
} else {
    byte[] heap = segment.getArray(); // use with ARRAY_BYTE_BASE_OFFSET + offset
}

Prevention

When it happens

Trigger: Calling getAddress() on a heap-backed segment (MemorySegmentFactory.wrap(byte[]), allocateUnpooledSegment) — usually to pass a raw pointer to unsafe code or native IO.

Common situations: Unsafe copy helpers that compute long pointers from segment.getAddress() + offset written for off-heap buffers but also invoked on heap segments; component reused between on-heap tests and off-heap production configurations.

Related errors


AI-assisted analysis of apache/flink@2f3c205e92 (2026-08-14). Data as JSON: /api/errors/cdcb7457ef182570. Report an issue: GitHub.