changes to the foreign preview API
Maurizio Cimadamore
maurizio.cimadamore at oracle.com
Tue Feb 1 12:48:49 UTC 2022
Hi,
as we've just integrated our first changeset which moves the Foreign
Function & Memory API into java.base (as a preview API), I'd like to
expand a bit more on the kind of API changes you might expect in the
upcoming weeks. Disclaimer: these changes will only apply to the
"foreign-preview" branch, so they won't affect the branch we currently
use to generate EA binaries (in case we need to apply quick fixes there).
First, you can expect us playing with the package name some more;
java.lang.foreign is really nothing more than an opening position, and
it is likely that we will move to a package hierarchy where the Memory
Access API and the Foreign Linker API live in two different packages
(e.g. java.X vs. java.X.invoke, for some value of X).
Secondly, on the renaming front, as anticipated in [1], we are also
planning a biggie rename from ResourceScope to MemorySession. This
renaming comes from the consideration that, currently there isn't always
a 1:1 relationship between a resource scope and a lexical scope (for
instance in case where a resource scope is stored in a field). We feel
that the MemorySession name is both more neutral w.r.t. suggesting any
correspondence with lexical scope and, at the same time more specific
(what's a "resource" ?).
We will also bring back the SegmentAllocator interface on MemorySession
- which means that you can just use methods on SegmentAllocator on a
MemorySession instance, which on the balance, works quite well, and
makes client code a bit more concise.
The other change we'd like to make is to remove the scope() accessors
from all the resources (MemorySegment, NativeSymbol, VaList). This comes
from a desire to make the API more principled: only the owner of a
scope/session should have the "right" to close it. In fact, we have
spent significant API estate (e.g. ResourceScope::whileAlive) just from
preventing random clients to shut down scopes. We now believe a better
approach would be to simply make the scope associated e.g. with a memory
segment inaccessible. In other words, a resource scope/memory session
becomes a _capability_: it is up to the owner of the scope/session to
decide who to share that capability with. Once a client has a scope, it
can close that scope, but also affect the scope by registering cleanup
actions, or allocating on that scope. Conversely, if a client only has a
segment, there's no way for that client to affect the owning
scope/session in a meaninful (and possibly, harmful) way.
Because of this, our plan is to drop API points to keep scopes/sessions
alive for longer than their creators intended. Internally, the API will
still make concurrent memory access safe, as well as protect segment
from being closed while in the middle of a native call (or an async
ByteBuffer IO operation). In fact, we think that the cases that are
secured by the memory/linker API internals already constitute the vast
majority of cases in which it makes sense to reach for a mechanism to
keep a scope/session open. If needs be, this leaves us space to add
other API methods in the future, such adding a simple higher-order
funtion to execute an action on a resource while keeping its scope open,
or, more generally, to add a scope dependency mechanism such as that
described in [2].
Finally, we would like to tweak the policy of the --enable-native-access
flag, as follows (this change was first discussed in [3]):
* when the flag is specified, we keep existing behavior. This means
getting an exception on every unsafe access, if the accessing module not
listed in the flag;
* when flag is not specified, access to unsafe functioalities is
allowed, with runtime warning.
The new, more-tolerant behavior in the absence of flag would facilitate
migration away from JNI in cases where altering the set of command line
options might be difficult. This mode would also help us (later) migrate
JNI to require a similar opt-in too, effectively putting both JNI and
Panama on the same grounds. The new mode is transitional and won't be
supported forever: in a future release, this mode will be disabled and
the new flag will be required _always_. This would give us more time to
improve the support for the --enable-native-access flag in cases where
e.g. it is currently problematic to alter the command line options
and/or to introduce a better way to propagate native dependencies across
modules.
This should pretty much cover it. With the exception of renaming of
classes and packages, we expect most of the idiomatic Panama code (such
as that in our jextract examples [4]) to remain indeed very similar to
its Java 18 counterpart.
Cheers
Maurizio
[1] - https://inside.java/2021/09/16/finalizing-the-foreign-apis/
[2] - https://inside.java/2021/05/28/taming-resource-scopes/
[3] -
https://mail.openjdk.java.net/pipermail/panama-dev/2022-January/016011.html
[4] -
https://github.com/openjdk/panama-foreign/blob/foreign-jextract/doc/panama_jextract.md
More information about the panama-dev
mailing list