MemorySegment.ofByteBuffer(ByteBuffer.allocateDirect())
Maurizio Cimadamore
maurizio.cimadamore at oracle.com
Mon Feb 7 12:19:34 UTC 2022
On 07/02/2022 10:57, Maurizio Cimadamore wrote:
> Ah, that's a bug, thanks.
Filed: https://bugs.openjdk.java.net/browse/JDK-8281334
Maurizio
>
> 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