MemorySegment.ofByteBuffer(ByteBuffer.allocateDirect())
    Michael Zucchi 
    notzed at gmail.com
       
    Sat Feb  5 11:27:03 UTC 2022
    
    
  
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