JDK-8303240 : Implementation of Foreign Function and Memory API (Third Preview)
  • Type: CSR
  • Component: core-libs
  • Priority: P3
  • Status: Closed
  • Resolution: Approved
  • Fix Versions: 21
  • Submitted: 2023-02-27
  • Updated: 2023-08-29
  • Resolved: 2023-04-24
Related Reports
CSR :  
Relates :  
Description
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 the `Arena::allocate` overloads which can be confusing.
 * The duality between `Arena` and `SegmentScope` 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 throws `UnsupportedOperationException` 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 the `Arena::allocate` overloads. See [this document][2].
 *  `SegmentScope` was dropped in favor of a much smaller construct `MemorySegment.Scope` which only has one predicate `isAlive()` and where the `equals()` method tests if two scopes model the same lifetime (and is alive). See [this document][2].
 * The factories `Arena::(openConfined, openShared)` were renamed to `Arena::(ofConfined, ofShared)`. The `SegmentScope.global()` factory was replaced by `Arena.global()`, while the `SegmentScope.auto()` factory was replaced by `Arena.ofAuto()`. Picking a more neutral name (`of` instead of `open`) was deemed necessary given that automatic arenas cannot be closed.
 * A fall-back linker based on [libffi][3] 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. The `MemorySegment::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 method `ValueLayout.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, namely `AddressLayout`.
 * 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][4]. 


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
-------------
 1. https://cr.openjdk.org/~mcimadamore/panama/why_lifetimes.html
 2. http://cr.openjdk.java.net/~mcimadamore/panama/scoped_arenas.html
 3. https://github.com/libffi/libffi
 4. https://github.com/openjdk/panama-foreign/pull/824

  [1]: https://cr.openjdk.org/~mcimadamore/panama/why_lifetimes.html
  [2]: http://cr.openjdk.java.net/~mcimadamore/panama/scoped_arenas.html
  [3]: https://github.com/libffi/libffi
  [4]: https://github.com/openjdk/panama-foreign/pull/824
Comments
Moving to Approved. Serving as the administrative Reviewer of the CSR; I assume members of the JEP 442 team agree that this iteration of the API is ready for JDK 21. As future work, I recommend including some kind of functionality to map from the name of a C type to the platform-specific ValueLayout it correspond to.
24-04-2023

Moving to Finalized.
14-04-2023

Moving to Provisional.
21-03-2023