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

Maurizio Cimadamore maurizio.cimadamore at oracle.com
Mon May 27 17:45:21 UTC 2019


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