{"record":{"id":"cdcb7457ef182570","repo":"apache/flink","slug":"memory-segment-does-not-represent-off-heap-memory","errorCode":null,"errorMessage":"Memory segment does not represent off heap memory","messagePattern":"Memory segment does not represent off heap memory","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"flink-core/src/main/java/org/apache/flink/core/memory/MemorySegment.java","lineNumber":306,"sourceCode":"    public ByteBuffer getOffHeapBuffer() {\n        if (offHeapBuffer != null) {\n            return offHeapBuffer;\n        } else {\n            throw new IllegalStateException(\"Memory segment does not represent off-heap buffer\");\n        }\n    }\n\n    /**\n     * Returns the memory address of off-heap memory segments.\n     *\n     * @return absolute memory address outside the heap\n     * @throws IllegalStateException if the memory segment does not represent off-heap memory\n     */\n    public long getAddress() {\n        if (heapMemory == null) {\n            return address;\n        } else {\n            throw new IllegalStateException(\"Memory segment does not represent off heap memory\");\n        }\n    }\n\n    /**\n     * Wraps the chunk of the underlying memory located between <tt>offset</tt> and <tt>offset +\n     * length</tt> in a NIO ByteBuffer. The ByteBuffer has the full segment as capacity and the\n     * offset and length parameters set the buffers position and limit.\n     *\n     * @param offset The offset in the memory segment.\n     * @param length The number of bytes to be wrapped as a buffer.\n     * @return A <tt>ByteBuffer</tt> backed by the specified portion of the memory segment.\n     * @throws IndexOutOfBoundsException Thrown, if offset is negative or larger than the memory\n     *     segment size, or if the offset plus the length is larger than the segment size.\n     */\n    public ByteBuffer wrap(int offset, int length) {\n        if (!allowWrap) {\n            throw new UnsupportedOperationException(\n                    \"Wrap is not supported by this segment. This usually indicates that the underlying memory is unsafe, thus transferring of ownership is not allowed.\");","sourceCodeStart":288,"sourceCodeEnd":324,"githubUrl":"https://github.com/apache/flink/blob/2f3c205e9266cb30240eb7f4fdab15cad629a70f/flink-core/src/main/java/org/apache/flink/core/memory/MemorySegment.java#L288-L324","documentation":"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.","triggerScenarios":"Calling getAddress() on a heap-backed segment (MemorySegmentFactory.wrap(byte[]), allocateUnpooledSegment) — usually to pass a raw pointer to unsafe code or native IO.","commonSituations":"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.","solutions":["Restrict getAddress() usage to segments where segment.isOffHeap() is true; for heap segments use getArray() plus sun.misc.Unsafe BYTE_ARRAY_BASE_OFFSET instead.","Prefer the segment's own copy/compare/swap methods (copyTo, copyFromUnsafe, compare, swapBytes) which handle both backings, removing the need for raw addresses.","If a long pointer is genuinely required, ensure the segment is allocated off-heap via MemorySegmentFactory.allocateOffHeapMemory."],"exampleFix":"// before\nlong ptr = segment.getAddress() + offset; // IllegalStateException on heap segment\n\n// after\nlong ptr = segment.isOffHeap()\n        ? segment.getAddress() + offset\n        : Unsafe.ARRAY_BYTE_BASE_OFFSET + offset; // combined with segment.getArray() as unsafe base","handlingStrategy":"validation","validationCode":"if (segment.isOffHeap()) {\n    long ptr = segment.getAddress() + offset;\n} else {\n    byte[] heap = segment.getArray(); // use with ARRAY_BYTE_BASE_OFFSET + offset\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat getAddress() as an off-heap-only API.","Prefer MemorySegment's built-in copy/compare methods over raw pointer arithmetic — they handle both backings safely."],"tags":["memory","unsafe","flink-core","api-misuse"],"backgroundTag":null,"analyzedSha":"2f3c205e9266cb30240eb7f4fdab15cad629a70f","analyzedAt":"2026-08-14T08:48:24.518Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}