[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