Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JNA: Support GraalVM #1608

Open
wants to merge 4 commits into
base: master
Choose a base branch
from

Commits on Jun 13, 2024

  1. Add support for GraalVM

    Adds a JAR publication at `jna-graalvm.jar`, with accompanying
    build infrastructure, which provides support for JNA within the
    context of the Substrate Virtual Machine (SVM).
    
    GraalVM Native Image targets use SVM instead of JVM at runtime.
    JNA's current strategy of unpacking libraries at runtime works
    under SVM, but is suboptimal; the binary is native, so it can
    simply include JNA object code for the current platform directly.
    
    To accomplish this, several GraalVM "feature" implementations are
    provided in this new publication. By default, regular JNA access
    is enabled through the `JavaNativeAccess` feature; this class
    enables reflection and runtime JNI configurations for downstream
    projects which use JNA.
    
    Another feature, `SubstrateStaticJNA`, is experimental because it
    relies on unstable GraalVM APIs, but instead of loading JNA at
    runtime from a dynamic library, it builds JNA into the final
    native image with a static object.
    
    These features are enabled through a resource within `META-INF`,
    called `native-image.properties`, which is picked up by the native
    image compiler at build time. The new artifact only needs to be
    present for GraalVM native targets at build time; otherwise, the
    classes and libraries in `jna-graalvm.jar` are inert.
    
    Includes tested support for:
    - macOS aarch64
    - Linux amd64
    
    - feat: add `jna-graalvm.jar` publication
    - feat: add base `JavaNativeAccess` feature for auto-config of JNA
    - feat: add initial implementation of `SubstrateStaticJNA` feature
    - test: sample/test gradle build for native image
    - chore: ci config to run native sample
    - chore: add readme to `lib/gvm`
    
    Signed-off-by: Sam Gammon <sam@elide.ventures>
    Signed-off-by: Dario Valdespino <dario@elide.ventures>
    Co-authored-by: Sam Gammon <sam@elide.ventures>
    Co-authored-by: Dario Valdespino <dario@elide.ventures>
    sgammon and darvld committed Jun 13, 2024
    Configuration menu
    Copy the full SHA
    5beedfc View commit details
    Browse the repository at this point in the history
  2. Static-compatible init of JNA native layer

    When operating under static linkage in SVM (Native Image), JNA's
    `JNI_OnLoad` hooks are not run. We need to sanity-check at the
    first JNI border and run static initialization manually.
    
    Additionally, `JNI_OnLoad` should be provided in static contexts
    as `JNI_OnLoad_jnidispatch`. This changeset fixes both issues.
    
    Signed-off-by: Sam Gammon <sam@elide.ventures>
    Signed-off-by: Dario Valdespino <dario@elide.ventures>
    sgammon committed Jun 13, 2024
    Configuration menu
    Copy the full SHA
    8deb7f2 View commit details
    Browse the repository at this point in the history
  3. Avoid polymorphic dispatch over JNI

    When linked statically on GraalVM, JNI symbols declared in the
    overloaded form cannot be resolved. Luckily, all of `Native`'s
    callsites are in `Pointer` or itself, and all `native` methods
    of `Native` are non-public.
    
    This PR adjusts the JNA C API to avoid using overloaded `read`,
    `write`, or `getDirectByteBuffer`. Callsites are amended in
    `Pointer` accordingly.
    
    Signed-off-by: Sam Gammon <sam@elide.ventures>
    Signed-off-by: Dario Valdespino <dario@elide.ventures>
    sgammon committed Jun 13, 2024
    Configuration menu
    Copy the full SHA
    748c981 View commit details
    Browse the repository at this point in the history
  4. Support JNA over Static JNI on GraalVM

    Implements a new optional linkage feature, called Static JNI, under
    GraalVM Native Image.
    
    With `com.sun.jna.SubstrateStaticJNA` enabled (opt-in), JNA is
    loaded eagerly at image build time, and then linked against a static
    copy of `libjnidispatch` at image link-time.
    
    The result is that `libjnidispatch.a` is embedded within the final
    image. No precursor library unpacking step is necessary before using
    JNA in this circumstance, because JNA's native layer is built
    directly into the image itself.
    
    - feat: implement static jni feature
    - chore: full gvm ci build
    - chore: add static jni sample
    
    Signed-off-by: Sam Gammon <sam@elide.ventures>
    Signed-off-by: Dario Valdespino <dario@elide.ventures>
    Co-authored-by: Sam Gammon <sam@elide.ventures>
    Co-authored-by: Dario Valdespino <dario@elide.ventures>
    sgammon and darvld committed Jun 13, 2024
    Configuration menu
    Copy the full SHA
    548ebec View commit details
    Browse the repository at this point in the history