Notes on packaging of native code in libraries
Maurizio Cimadamore
maurizio.cimadamore at oracle.com
Fri Feb 24 15:09:45 UTC 2023
On 24/02/2023 14:45, Mike Hearn wrote:
> Especially once Panama ships the Java ecosystem could strongly benefit
> from a standardization of how native components are bundled into and
> loaded from libraries, as current build systems and the JVM tooling
> don't have much to say on the topic. The result is a lot of wheel
> reinvention across the ecosystem in the form of
> NativeLibraryLoader.java classes, always unique per project, and a
> bunch of bugs / developer friction that doesn't need to happen.
I tend to agree with the overall assessment. Shipping native libraries
with Java projects is a known pain point, and it would be nice to have
some solution for that. That being said, while I'm aware that the best
way to make things work in today's world is by shipping native libraries
in a jar, and then extract them _somewhere_, so that they can be loaded
with `System::loadLibrary`, I'm not sure how much that can be viewed as
a full solution, rather than a workaround. I can imagine cases where
extracting libraries into a custom folder is not feasible (e.g. because
of missing permissions). My general feeling is that, with jars and
native libraries it's like trying to fit a round peg in a square hole:
surely you can devise some pragmatic solution which makes things sort of
work, but what you get is always a little brittle.
If you look at what we did for jextract [1], the approach we used was
different: jextract is written entirely in Java, but has a dependency
(via Foreign Function & Memory API) on libclang. When we build jextract,
we create a jmod [2] for jextract, with the native library for libclang
in the right place. We then create a JDK image which contains
jdk.compiler, java.base and the newly created jextract module. The
resulting JDK will have the libraries in the right place. This means
that we can provide a launcher simply by calling jextract's entry point
using the custom JDK image. You can run jextract and run all jextract
tests against this custom image, which then requires zero extra custom
arguments passed on the command line (because the native libraries are
added in the right place already).
An approach such as this seems more promising than doing heroics with
jarfiles, at least for applications, and one that could be more amenable
to things like code signing (in jextract we don't do this, but I don't
see why that could not be added).
Maurizio
[1] - https://jdk.java.net/jextract/
[2] - https://github.com/openjdk/jextract/blob/master/build.gradle
>
> The good news is that all this would be very cheap to improve. All
> that's needed is:
>
> * A defined layout for JARs (or JMODs) that standardizes where to
> place native libraries given an OS and CPU architecture.
>
> * Tooling that extracts native code to a user-specified directory
> that's then appended to the java.library.path at runtime (e.g. a
> flag to the java launcher?), so that once build systems learn to
> pass this flag or do the extraction themselves library authors can
> just deprecate and eventually remove all their custom loader code
> (which is large, complex, copy/pasted between projects and
> inconsistent).
>
> * Support for that mechanism in jlink.
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/leyden-dev/attachments/20230224/d591806d/attachment.htm>
More information about the leyden-dev
mailing list