[foreign-memaccess] RFR 8224843: Refine ByteBuffer interop support

Maurizio Cimadamore maurizio.cimadamore at oracle.com
Tue May 28 13:40:03 UTC 2019


Had a chat with Alan,
there's no way to unmap a MBB - but what other tests do is something 
like this

             var ref = new WeakReference<>(mbb);
             mbb = null;
             System.gc();
             while (ref.get() == null) {
                 Thread.sleep(20);
             }


I'll add this.

Thanks
Maurizio

On 28/05/2019 14:20, Jorn Vernee wrote:
> I'm getting an error on the new test:
>
> TEST RESULT: Error. failed to clean up files after test
>
> This is probably because a stream to a file is not closed (which is 
> problematic for Windows), though I can't spot where that's happening. 
> I assume a MappedByteBuffer is un-mapped when the FileChannel is 
> closed? (there doesn't seem to be a close/unmap method on MBB).
>
> Jorn
>
> Maurizio Cimadamore schreef op 2019-05-28 14:32:
>> Updated webrev:
>>
>> http://cr.openjdk.java.net/~mcimadamore/panama/8224843_v2/
>>
>> Changes:
>>
>> * fixed byte buffer template
>>
>> * regularized logic for resize (now bytebuffer segments also get to 
>> resize()!)
>>
>> * moved byte buffer segment into its own class
>>
>> * added several more test to check correctness of resize operation
>> with various segment kinds
>>
>> * opened up MemorySegment.ofArray to allow all primitive arrays (but
>> MemoryAddress.asByteBuffer will still throw if the base object is not
>> byte[])
>>
>> Maurizio
>>
>> On 28/05/2019 12:22, Maurizio Cimadamore wrote:
>>> I'll check - thanks
>>>
>>> Maurizio
>>>
>>> On 28/05/2019 11:30, Jorn Vernee wrote:
>>>> Hi,
>>>>
>>>> The patch doesn't compile for me:
>>>>
>>>> === Output from failing command(s) repeated here ===
>>>> * For target jdk_modules_java.base__the.java.base_batch:
>>>> h:\cygwin64\home\Jorn\cygwin-projects-new\memaccess\src\java.base\share\classes\java\nio\ScopedByteBuffer.java:41: 
>>>> error: no suitable constructor found for ByteBuffer(no arguments)
>>>>         super();
>>>>         ^
>>>>     constructor ByteBuffer.ByteBuffer(int,int,int,int,byte[],int) 
>>>> is not applicable
>>>>       (actual and formal argument lists differ in length)
>>>>     constructor ByteBuffer.ByteBuffer(int,int,int,int) is not 
>>>> applicable
>>>>       (actual and formal argument lists differ in length)
>>>> h:\cygwin64\home\Jorn\cygwin-projects-new\memaccess\src\java.base\share\classes\java\nio\ScopedByteBuffer.java:477: 
>>>> error: put(byte[]) in ScopedByteBuffer cannot override put(byte[]) 
>>>> in ByteBuffer
>>>>     public ByteBuffer put(byte[] src) {
>>>>                       ^
>>>>   overridden method is final
>>>> h:\cygwin64\home\Jorn\cygwin-projects-new\memaccess\src\java.base\share\classes\java\nio\ScopedByteBuffer.java:484: 
>>>> error: hasArray() in ScopedByteBuffer cannot override hasArray() in 
>>>> ByteBuffer
>>>>    ... (rest of output omitted)
>>>>
>>>> * All command lines available in 
>>>> /cygdrive/h/cygwin64/home/Jorn/cygwin-projects-new/memaccess/build/windows-x86_64-server-release/make-support/failure-logs.
>>>> === End of repeated output ===
>>>>
>>>> I see that in the patch you made the necessary changes to 
>>>> java.nio.Buffer, but shouldn't these changes be made to the 
>>>> template file for ByteBuffer as well? Since ScopedByteBuffer 
>>>> extends ByteBuffer?
>>>>
>>>> Jorn
>>>>
>>>> Maurizio Cimadamore schreef op 2019-05-27 19:45:
>>>>> Hi,
>>>>> as you know, the foreign memory access API supports bidirectional
>>>>> interop between MemoryAddress and ByteBuffer:
>>>>>
>>>>> 1) MemorySegment::ofByteBuffer(ByteBuffer)
>>>>> 2) MemoryAddress:;asDirectByteBuffer(int bytes)
>>>>>
>>>>> That is (1) can be used to create a memory segment out of an existing
>>>>> byte buffer, whereas (2) can be used to do the opposite, that is, to
>>>>> convert a memory address into a byte buffer.
>>>>>
>>>>> While (1) works pretty reliably (but I've added some tests for it),
>>>>> the implementation for (2) leaves to be desired:
>>>>>
>>>>> * The resulting byte buffer is unaware of the fact that the backing
>>>>> memory is attached to a scope that can be closed
>>>>> * There's no way to create a buffer if the address encapsulates some
>>>>> heap-based memory address
>>>>>
>>>>> This patch solves both issues - and also adds a supported way for
>>>>> creating a memory segment out of a heap-allocated byte array
>>>>> (MemorySegment.ofArray(byte[])) which I think is useful.
>>>>>
>>>>> To solve the scope awareness issue I put together (after discussing
>>>>> extensively with Alan, CC'ed) a delegating wrapper of ByteBuffer,
>>>>> which delegates to the underlying buffer implementation after doing a
>>>>> liveness check on the owning scope. That means that operations 
>>>>> such as
>>>>> ByteBuffer::getInt will only succeed if the scope the view is
>>>>> associated with is still alive. Note that we need the wrapping 
>>>>> only if
>>>>> the associated scope is _not_ pinned - in fact, if the scope is
>>>>> pinned, then it can't be closed, so there's no need to check for
>>>>> liveliness.
>>>>>
>>>>> To do this I had to remove the 'final' modifier from some instance
>>>>> methods in ByteBuffer and Buffer - the theory here is that these
>>>>> 'final' have been added in early days to help the VM out, but are not
>>>>> necessary now (also note that is not possible for a client to 
>>>>> create a
>>>>> custom byte buffer implementation, as all constructors are
>>>>> package-private).
>>>>>
>>>>> Finally, the wrapped byte buffer implementation does not support
>>>>> typeful views such as 'asCharBuffer' - this is tricky to support as
>>>>> CharBuffer is not a subtype of ByteBuffer so, to go down that path
>>>>> we'd need to wrap also CharBuffer and friends, which is doable, but
>>>>> we're leaning towards YAGNI for now.
>>>>>
>>>>> Finally I've added a test which writes into memory (using var 
>>>>> handles)
>>>>> then reads it back using a segment-backed byte buffer (there are 
>>>>> tests
>>>>> for both heap and off-heap variants of the buffer). There's also a
>>>>> test which checks interop between MappedByteBuffer and the foreign 
>>>>> API
>>>>> (which will likely be relevant in the context of JEP 352 [1]), and,
>>>>> finally, a test which makes sure that all instance method in the
>>>>> scope-wrapped buffer throws ISE after the scope has been closed.
>>>>>
>>>>> Webrev:
>>>>>
>>>>> http://cr.openjdk.java.net/~mcimadamore/panama/8224843/
>>>>>
>>>>> Comments welcome!
>>>>>
>>>>> Cheers
>>>>> Maurizio
>>>>>
>>>>> [1] - https://openjdk.java.net/jeps/352


More information about the panama-dev mailing list