graal icon indicating copy to clipboard operation
graal copied to clipboard

[GR-18218] Full support for the Foreign Function & Memory API in Native Image

Open fniephaus opened this issue 1 year ago • 21 comments

TL;DR

Add full support for the Foreign Function & Memory API (JEP 454) to Native Image.

Goals

The Foreign Function & Memory (FFM) API became GA in JDK 22, a new API "by which Java programs can interoperate with code and data outside of the Java runtime."

Since GraalVM for JDK 22, most features of the FFM API are already supported (see release notes). Support for Arena.ofShared is still experimental and therefore needs to be enabled with option -H:+SharedArenaSupport at image build time. Full support for the FFM API is ongoing work. Note that GraalVM for JDK 22 and later support the FFM API on HotSpot (e.g. when Graal is used as a JIT compiler).

As part of #7152 and #7238, we have already added preliminary support for foreign downcalls and an infrastructure to support upcalls in the future. Documentation on what parts of the FFM API work with Native Image and how they can be used can be found here.

Missing Features / Open Tasks

  • [x] Shared arenas (i.e. Arena.ofShared())
  • [ ] Improve downcall performance (currently always unoptimized)
  • [x] Improve upcall performance (currently always unoptimized)
  • [x] Agent support
  • [ ] Platform support
    • [x] missing for Linux AArch64
    • [x] missing for Windows AMD64
    • [x] missing for MacOS AMD64
    • [x] missing for MacOS AArch64

Non-Goals

  • It is not a goal to complete the support for the FFM API in time for the release of GraalVM for JDK 22
  • It is not a goal to drop support for JNI or the Native Image C API

Related PRs

  • https://github.com/oracle/graal/pull/7152
  • https://github.com/oracle/graal/pull/7238
  • https://github.com/oracle/graal/pull/7980
  • https://github.com/oracle/graal/pull/10168
  • https://github.com/oracle/graal/pull/10235
  • https://github.com/oracle/graal/pull/10788
  • https://github.com/oracle/graal/pull/10856
  • https://github.com/oracle/graal/pull/11125
  • https://github.com/oracle/graal/pull/11311
  • https://github.com/oracle/graal/pull/11270
  • https://github.com/oracle/graal/pull/11335

fniephaus avatar Jan 05 '24 15:01 fniephaus

Is there an issue where we can track support for (downcalls) on ARM64 (aka aarch64)?

msgilligan avatar Mar 20 '24 20:03 msgilligan

Is there an issue where we can track support for (downcalls) on ARM64 (aka aarch64)?

@msgilligan I would consider this to be in the scope of this roadmap item: JEP 454 includes aarch64, so full support in Native Image means that it works on all supported platforms including aarch64 on Linux/macOS.

fniephaus avatar Mar 21 '24 11:03 fniephaus

One example of an upcall not working (yet) is described in #8616 AFAIUI.

jerboaa avatar Mar 28 '24 09:03 jerboaa

@fniephaus Going by https://github.com/oracle/graal/discussions/8677 there should be better support for JEP 454 in latest master (commit https://github.com/oracle/graal/commit/7b51429d1c19595c1e9ddd8e3002159cd345dcae). Is that supposed to fix the test case from https://github.com/oracle/graal/issues/8616? It doesn't for me, fwiw. Just checking.

jerboaa avatar Apr 09 '24 16:04 jerboaa

@jerboaa despite the dynamic nature of the JEP 454 foreign call API, GraalVM Native Image needs to generate stub code for such calls ahead of time, which requires configuration or registration (like JNI calls do). Have a look at the org.graalvm.nativeimage.hosted.RuntimeForeignAccess class for use from a Feature. Also, any downcall method handles or upcall stubs must be created at runtime (with a Linker). It is not supported to create them during the image build and carry them over to runtime using the image heap. As a consequence of this and of dealing only with signatures, the calls use a generic method handle dispatch with little margin for optimization and also, upcall target methods further need to be registered for reflective access so that they can be called by method handle.

peter-hofer avatar Apr 09 '24 16:04 peter-hofer

@jerboaa despite the dynamic nature of the JEP 454 foreign call API, GraalVM Native Image needs to generate stub code for such calls ahead of time, which requires configuration or registration (like JNI calls do).

I take it the native image agent won't help with that kind of registration config generation?

Have a look at the org.graalvm.nativeimage.hosted.RuntimeForeignAccess class for use from a Feature. Also, any downcall method handles or upcall stubs must be created at runtime (with a Linker). It is not supported to create them during the image build and carry them over to runtime using the image heap. As a consequence of this and of dealing only with signatures, the calls use a generic method handle dispatch with little margin for optimization and also, upcall target methods further need to be registered for reflective access so that they can be called by method handle.

OK thanks! Is there some documentation describing how this is supposed to get used going forward? Or maybe there are some examples I could look at? It sounds like #8616 won't work verbatim...

jerboaa avatar Apr 09 '24 17:04 jerboaa

The agent does not generate a foreign API configuration, but I believe it would catch the target methods for upcalls that are needed in the reflection configuration. We have this documentation page: https://www.graalvm.org/jdk23/reference-manual/native-image/native-code-interoperability/foreign-interface/ I believe that for #8616, registering the FunctionDescriptor objects for foreign calls and FFM.compare for method handle calls should suffice.

peter-hofer avatar Apr 09 '24 17:04 peter-hofer

Thanks, I'll give that a go.

jerboaa avatar Apr 09 '24 17:04 jerboaa

@peter-hofer Good afternoon! I would like to ask if there are plans to add dynamic call of native method without mandatory registration at the build stage?

Arcane561 avatar Sep 11 '24 14:09 Arcane561

@Arcane561 we are working on a mechanism that picks up the method handles that jextract generates without mandatory registration, but it expect it to be a while longer. @fangerer

peter-hofer avatar Sep 11 '24 15:09 peter-hofer

Only jextract generated ones, or any handles following some supported patterns?

chrisvest avatar Sep 11 '24 17:09 chrisvest

Hello, has there be progress to support arm64 downcall, but maybe upcall too ?

Some part of the JDK already use FFM which tends to be problematic e.g. to run image generation (which do some layout stuff with fonts).

EDIT: looking up the message I see this limitation is still in actual: https://github.com/oracle/graal/blob/d5c7b8aab207e8d6ad0eef494e316bdfdd5a4ebf/substratevm/src/com.oracle.svm.hosted.foreign/src/com/oracle/svm/hosted/foreign/ForeignFunctionsFeature.java#L221

bric3 avatar Jan 08 '25 22:01 bric3

@bric3 work is underway on aarch64 support for the FFM API.

peter-hofer avatar Jan 09 '25 09:01 peter-hofer

Do you know if this can make it for 24?

Regardless this is exciting, and I can only thank you and all involved.

bric3 avatar Jan 09 '25 09:01 bric3

@bric3 that seems unlikely, but we expect it will be part of the upcoming 25 LTS release.

peter-hofer avatar Jan 09 '25 09:01 peter-hofer

Thank you for the heads-up, I'm looking forward to it :)

bric3 avatar Jan 09 '25 09:01 bric3

AArch64 support for Linux and Darwin landed today: https://github.com/oracle/graal/pull/10856

lewurm avatar Mar 14 '25 09:03 lewurm

AArch64 support for Linux and Darwin landed today: #10856

@lewurm Will there be a GraalVM 24 release with full support? Or is this only for GraalVM 25?

alexarchambault avatar Apr 03 '25 14:04 alexarchambault

@alexarchambault This will only be for GraalVM 25 (and newer, ofc).

fangerer avatar Apr 03 '25 14:04 fangerer

@alexarchambault This will only be for GraalVM 25 (and newer, ofc).

Thanks! Looking forward to GraalVM 25 then

alexarchambault avatar Apr 03 '25 14:04 alexarchambault

@alexarchambault This will only be for GraalVM 25 (and newer, ofc).

Thanks! Looking forward to GraalVM 25 then

If you are adventurous you can try out GraalVM 25 dev builds, e.g.: https://github.com/graalvm/graalvm-ce-dev-builds/releases/tag/25.0.0-dev-20250403_0843

lewurm avatar Apr 03 '25 17:04 lewurm

Is support for the LLVM backend planned? I built graalvm 26 from the latest commit and got: Error: Support for the Foreign Function and Memory API is not available with the LLVM backend.

theoparis avatar Aug 10 '25 20:08 theoparis

@theoparis it's because llvm/clang written on C++, not C, you can try to relink it by yourself, accepted answer can help you: https://stackoverflow.com/questions/68502293/cant-link-against-self-built-llvm-api

acuna-public avatar Aug 17 '25 18:08 acuna-public

@acuna-public Graalvm builds fine, it just doesn't seem to support FFM. I'm trying to use the llvm backend of graalvm with -H:CompilerBackend=llvm.

theoparis avatar Aug 17 '25 20:08 theoparis

Once FFM support is complete, maybe Oracle could start porting JNI usage within the JDK itself to FFM. Would greatly simplify supporting the JDK.

pquiring avatar Sep 23 '25 20:09 pquiring

Extended support has been delivered in GraalVM 25, for more details see the Foreign Function and Memory API in Native Image documentation.

alina-yur avatar Sep 24 '25 15:09 alina-yur

Extended support has been delivered in GraalVM 25, for more details see the Foreign Function and Memory API in Native Image documentation.

Super-cool @alina-yur! Both graalvm-ce and graalvm-oracle on Nixpkgs have been upgraded to 25.

I've got a really cool Open Source library/app that works with native-image and uses FFM to call a native cryptography library. Since I develop on aarch64, release 25 GA means I can release it soon!

msgilligan avatar Sep 24 '25 16:09 msgilligan

I've got a really cool Open Source library/app that works with native-image and uses FFM to call a native cryptography library. Since I develop on aarch64, release 25 GA means I can release it soon!

@msgilligan very cool, thank you for feedback, Sean! Glad to see it being used in your project. Share with us once you release it :)

alina-yur avatar Sep 25 '25 15:09 alina-yur

Glad to see it being used in your project. Share with us once you release it :)

@alina-yur Release 0.2 is happening this week. It's an Elliptic Curve Cryptography library and I'm giving a presentation about it Tuesday night (Nov 4th) at Stanford so it's becoming real! What's the best way for me to contact you directly? (I follow you on both X and Blue Sky)

The repo is https://github.com/bitcoinj/secp256k1-jdk and the schnorr-example sample app is compiled with GraalVM and uses the native libsecp256k1 library via FFM.

msgilligan avatar Nov 04 '25 09:11 msgilligan

@msgilligan good luck with your presentation! yes, just send me a link to your presentation/announcement anywhere and I'll be happy to repost it:)

alina-yur avatar Nov 04 '25 11:11 alina-yur