JPassport
JPassport
JPassport works like [Java Native Access (JNA)](https://github.com/java-native-access/jna) but uses the [Foreign Function and Memory API](https://openjdk.java.net/jeps/393) (FFM) instead of JNI. Similar to JNA, you declare a Java interface that is bound to the external C library using method names. The goal of this project is to provide a JNA-like experience for anyone wanting to access native code. The project is written primarily in Java, distributed under the Apache License 2.0 license, first published in 2021. Key topics include: ffi, ffm-api, foreign-function-and-memory-api, foreign-linker, java.
JPassport - Java 24
JPassport works like Java Native Access (JNA) but uses the
Foreign Function and Memory API (FFM) instead of JNI.
Similar to JNA, you declare a Java interface that is bound to the external C library using method names.
The goal of this project is to provide a JNA-like experience for anyone wanting to access native code.
JNA is a much more mature project than this one and, it supports Java 8 and earlier.
JPassport was able to build on new language features to make this library (hopefully) simpler to use.
If you cannot use a recent Java version then JNA is your best bet. However, if you can use a recent JRE then
this library is much lighter weight than JNA (100 kb vs 3+ MB) and the programing should be simpler
for many cases. I also hope that in simple cases, changing to JPassport from existing JNA code shouldn't be
an onerous task.
The FFM team maintain a tool called JExtract. Given a header file (.h), JExtract will write the required
Java code to access the native code described in the header. In order to use the code it generates you need
to be somewhat familiar with FFM and, if I understand correctly,
for proper struct support you need to have it generate code for each platform you want to support.
In terms of performance, JExtract and JPassport are nearly identical. Since JExtract leaves you dealing
directly with FFM calls it could get performance gains by directly optimizing the calls you make (ex.
you do not need to read back all fields in a struct).
Whether jextract or JPassport is a better tool for you depends on a) how large is your C API, b) where do
you want the cognitive load. For large header files, jextract will create the code very quickly and
it will be correct (i.e. argument ordering will always be right). However, in my experiment using jextract
on blis I found that jextract produced a truly unusable API (>125k lines of code).
Since you need to build the interface
file and records yourself in JPassport, you could make a mistake. Jextract puts the cognitive load on every
function call you make, since you need to know lots about FFM to use the generated code. JPassport puts
the cognitive load on building the interfaces and records. When using JPassport you do not need to know
any FFM, it should look like bland Java code.
Java 24 and later are required to use this library. There are separate branches for Java 17 to 22.
FFM is final in
Java 22. The Class-file API is final in Java 24.
Contents
- Getting Started
- Automatically generating JPassport interfaces
- Calling native code
- Callbacks
- Data type mapping
- Annotations
- Trouble Shooting
- Performance
- Limitations
- Release notes
Getting Started
Source
Download the source and run the maven build, or use the maven dependency:
<dependency>
<groupId>io.github.boulder-on</groupId>
<artifactId>JPassport</artifactId>
<version>1.5.0-24</version>
</dependency>
Dependencies
JPassport itself only requires Java 24 or later to build and run. There are separate Java 17-22 branches.
Future work
If JPassport does not appear to meet your needs, or you're not sure how to accomplish what you
want with JPassport, please send me a message or open an issue.
Contributors
Showing top 2 contributors by commit count.
