MemorySegment.ofByteBuffer(ByteBuffer.allocateDirect())
Maurizio Cimadamore
maurizio.cimadamore at oracle.com
Mon Feb 7 10:57:28 UTC 2022
Ah, that's a bug, thanks.
It should create a non-closeable global scope that keeps reference the
byte buffer. We have that code to keep class loaders alive:
ResourceScopeImpl.heapScope(bb);
Maurizio
On 05/02/2022 11:27, Michael Zucchi wrote:
>
> Evening,
>
> I'm seeing a direct ByteBuffer being freed while still used by a
> MemorySegment.ofByteBuffer(). I'm apparently using foreign-jextract
> @ commit 6c3e90789b1a6590894f09c2027a7fcf9e23af06 (Fri Jan 28 11:01:26
> 2022) but it hasn't changed for months.
>
> The docs for ofByteBuffer() explicitly state the backing buffer is
> referenced.
>
> /**
> * Creates a new buffer memory segment that models the memory
> associated with the given byte
> * buffer. The segment starts relative to the buffer's position
> (inclusive)
> * and ends relative to the buffer's limit (exclusive).
> * <p>
> * If the buffer is {@link ByteBuffer#isReadOnly() read-only}, the
> resulting segment will also be
> * {@link ByteBuffer#isReadOnly() read-only}. The scope associated
> with this segment can either be the
> * {@linkplain ResourceScope#globalScope() global} resource scope,
> in case the buffer has been created independently,
> * or some other resource scope, in case the buffer has been
> obtained using {@link #asByteBuffer()}.
> * <p>
> * The resulting memory segment keeps a reference to the backing
> buffer, keeping it <em>reachable</em>.
> *
> * @param bb the byte buffer backing the buffer memory segment.
> * @return a new buffer memory segment.
> */
>
> But I don't see how it could be looking at
> AbstractMemorySegmentImpl.ofBuffer(), it just creates the segment
> using (long, long, int, scope)
>
> public static AbstractMemorySegmentImpl ofBuffer(ByteBuffer bb) {
> ...
> return new NativeMemorySegmentImpl(bbAddress + pos, size,
> modes, bufferScope);
> ...
> }
>
> For what it's worth this is the code i'm using. IntArray is just a
> thin wrapper over MemorySegment.
>
> IntArray loadSPIRV(String name) throws IOException {
> try (InputStream is =
> TestVulkan.class.getResourceAsStream(name)) {
> ByteBuffer bb =
> ByteBuffer.allocateDirect(8192).order(ByteOrder.nativeOrder());
> int length = Channels.newChannel(is).read(bb);
>
> bb.position(0);
> bb.limit(length);
>
> return IntArray.create(MemorySegment.ofByteBuffer(bb));
> }
> }
> IntArray mandelbrot_cs;
>
> void demo() throws Exception {
> mandelbrot_cs = loadSPIRV("mandelbrot.bin");
>
> ... at some point later and before i use it it's junk, vulkan
> crashes ...
> }
>
> If I keep a hard reference to 'bb' then it works fine indicating it's
> probably getting gc'd otherwise.
>
> ByteBuffer bb;
>
> IntArray loadSPIRV(String name) throws IOException {
> ...
> bb.position(0);
> bb.limit(length);
>
> this.bb = bb;
> ...
> }
>
> This version of loadSPIRV works fine:
>
> IntArray loadSPIRV(String name) throws IOException {
> try (InputStream is =
> TestVulkan.class.getResourceAsStream(name)) {
> MemorySegment seg =
> ((SegmentAllocator)scope).allocateArray(Memory.INT, 2048);
> int length =
> Channels.newChannel(is).read(seg.asByteBuffer());
>
> return IntArray.create(seg.asSlice(0, length));
> }
> }
>
>
> Regards,
> !Z
More information about the panama-dev
mailing list