Summary
This CSR refers to the third preview iteration of the Foreign Function & Memory (FFM) API originally targeted for Java 19, with the goal of further refining and consolidating the FFM API.
Problem
Feedback on the previously incubating API revealed the following issues:
- There are two ways to allocate memory that are equivalent via either the overloads of
MemorySegment::allocateNative
or via theArena::allocate
overloads which can be confusing. - The duality between
Arena
andSegmentScope
is a source of confusion: in almost all cases, client code creates arenas, but then has to retrieve the arena scope to interact with other APIs (e.g.Linker::upcallStub
). - The
Linker::nativeLinker
method throwsUnsupportedOperationException
for unsupported platforms. - The FFM API allows creation of some memory layouts (e.g. padding layouts) whose size is not a multiple of 8 bits, even though such layouts are not well supported.
- The restricted methods for adapting the size and scope of a (zero-length) memory segment are hard to use, especially to resize existing segments (which is a fairly common operation when interacting with native libraries).
- The
VaList
construct is neither used in the JDK nor in third-party libraries. - The mechanism for creating unbounded address layouts is overly unrestricted.
- It is not possible to use linker options for upcalls. This might be useful in the future, e.g. to specify custom policies to handle uncaught exceptions.
- The handling of
CaptureCallState
(e.g. for "errno") does not take into account unsupported runtime values (e.g. the same capture layout is exposed for both Linux and Windows). - The performance of very short-lived native calls (like
clockgettime
) could be improved. - Checking sequence and group layout constraints can be made upon layout construction instead of throwing an exception later when a
VarHandle
is constructed.
Solution
Here we describe the main changes brought forward in this CSR:
- The static factory
MemorySegment::allocateNative
overloads have been removed. Instead, allocation is made via theArena::allocate
overloads. See this document. SegmentScope
was dropped in favor of a much smaller constructMemorySegment.Scope
which only has one predicateisAlive()
and where theequals()
method tests if two scopes model the same lifetime (and is alive). See this document.- The factories
Arena::(openConfined, openShared)
were renamed toArena::(ofConfined, ofShared)
. TheSegmentScope.global()
factory was replaced byArena.global()
, while theSegmentScope.auto()
factory was replaced byArena.ofAuto()
. Picking a more neutral name (of
instead ofopen
) was deemed necessary given that automatic arenas cannot be closed. - A fall-back linker based on libffi was added to simplify porting (see https://github.com/openjdk/panama-foreign/pull/770 for details).
- The memory layout API now uniformly enforces that bit-size and bit-alignment constraints of all memory layouts (including padding layouts) must be a multiple of 8.
- A new restricted instance method, namely
MemorySegment::reinterpret
, was added. This allows to create a new native segment, with new size and segment scope with the same base address as some existing segment. Some overloads are also provided, for usability. TheMemorySegment::ofAddress
method is kept, as a way to create a zero-length native memory segment from a raw long address. As such, this method is no longer restricted. - The
VaList
interface was dropped. - The
ValueLayout.OfAddress::asUnbounded
method was replaced with the new methodValueLayout.OfAddress::withTargetLayout
, which allows to associate an address layout with a "target" layout (the layout of the memory region pointed to by a given address). This allows the API to expose a new kind of "dereference"PathElement
, which can be used to create access var handles for expression such as*(a.b)[10]
. Also, given the importance of address layouts,ValueLayout.OfAddress
was moved to a toplevel class, namelyAddressLayout
. - Linker options can now be used when creating upcall stubs. (Note: at the time of writing there are no supported linker options for upcall stubs).
- The
CapturedCallState
interface was removed. A new static method was added to query the layout of the runtime values to be preserved. This layout is now platform specific. - A new linker option was added to mark calls to native functions that are extremely short-lived (comparable to a no-op) and do not call back into Java (we call such functions "trivial functions"). This option might be used by the linker to speed up a native call (e.g. by removing thread state transitions).
- Up-front checks are added in the sequence and group constructors as well as in the associated
withBitAlignment()
methods making sure the layouts are well formed.
Specification
A specdiff and javadoc of the changes as of 2023-04-13 are available below:
- https://cr.openjdk.org/~pminborg/panama/21/v2/specdiff/overview-summary.html
- https://cr.openjdk.org/~pminborg/panama/21/v2/javadoc/api/java.base/java/lang/foreign/package-summary.html
References
- csr of
-
JDK-8304265 Implementation of Foreign Function and Memory API (Third Preview)
-
- Resolved
-
- relates to
-
JDK-8312523 Implementation of Foreign Function & Memory API
-
- Closed
-