8347047: Cleanup action passed to MemorySegment::reinterpret keeps old segment alive

Reviewed-by: mcimadamore
This commit is contained in:
Per Minborg 2025-01-08 08:44:22 +00:00
parent bcefab5e55
commit b0c935c03e

View file

@ -145,12 +145,17 @@ public abstract sealed class AbstractMemorySegmentImpl
Reflection.ensureNativeAccess(callerClass, MemorySegment.class, "reinterpret", false); Reflection.ensureNativeAccess(callerClass, MemorySegment.class, "reinterpret", false);
Utils.checkNonNegativeArgument(newSize, "newSize"); Utils.checkNonNegativeArgument(newSize, "newSize");
if (!isNative()) throw new UnsupportedOperationException("Not a native segment"); if (!isNative()) throw new UnsupportedOperationException("Not a native segment");
Runnable action = cleanup != null ? Runnable action = cleanupAction(address(), newSize, cleanup);
() -> cleanup.accept(SegmentFactories.makeNativeSegmentUnchecked(address(), newSize)) :
null;
return SegmentFactories.makeNativeSegmentUnchecked(address(), newSize, scope, readOnly, action); return SegmentFactories.makeNativeSegmentUnchecked(address(), newSize, scope, readOnly, action);
} }
// Using a static helper method ensures there is no unintended lambda capturing of `this`
private static Runnable cleanupAction(long address, long newSize, Consumer<MemorySegment> cleanup) {
return cleanup != null ?
() -> cleanup.accept(SegmentFactories.makeNativeSegmentUnchecked(address, newSize)) :
null;
}
private AbstractMemorySegmentImpl asSliceNoCheck(long offset, long newSize) { private AbstractMemorySegmentImpl asSliceNoCheck(long offset, long newSize) {
return dup(offset, newSize, readOnly, scope); return dup(offset, newSize, readOnly, scope);
} }