First8 is gespecialiseerd in het pragmatisch ontwikkelen van bedrijfskritische Java toepassingen waarbij integratie van systemen, hoge eisen aan beveiliging en veel transacties een belangrijke rol spelen. Op deze pagina vindt je onze blogs. Op www.first8.nl vind je ons nieuws, de agenda, vacatures en meer.

Native code interop with JNA

In enterprise situations you will often find a mashup of polyglot systems, many systems and many languages working together. The glue that commonly binds different systems are databases. You can imagine though, that going through the database, using a network connection, is not always always suitable. In many cases a simple local in-process call offers the necessary performance gains.

For interaction with native code there are many libraries and frameworks that offer help. The default way for Java would be JNI, which is targeted to C/C++ and just not that simple to use. Mapping different data structures is the main problem.
Going from Java through C to Fortran, the target language in our case, actually requires twice the memory type mapping and conversion code meaning double the pain. Using JNA instead (skipping the C in-between code), is relatively easy and simple, as you will see.

In this example Fortran will be used as the target language that produces the native (compiled) library to interact with. Note that any language could have produced the actual native library, though things like method signatures and data formats will vary wildly! Even when staying with one language, different compilers, compiler options, platforms, etc. can have dramatic effects on the nitty-gritty details that make an actual native call either work or fail.

Requirements:

  • Java JDK, installed
  • Groovy, installed and on the path
  • gfortran, install using a package manager

Fortran (hello.f95)
An example piece of Fortran code (disclaimer: I’m not a Fortran programmer ;D).
It prints the two inputs and returns a simple String through an output parameter (yep, that’s not even possible in Java, but common in Fortran).

The groovy shell script (libgreet.groovy.sh)
The shell script calls the native library. It uses the Grape system to grab the JNA library from the public maven repositories. To be able to call a native piece of code, you will need to define the interface you expect. This is not actually checked when compiling, the call will be made dynamically in runtime and fail when it turns out to be incorrect.

Hey it’s not C
Reading the output parameter requires JNA Pointer magic which kinda resembles the way it works in C(++). The fun thing about Fortran is that is handles strings in the same way as java does (in memory), which actually makes interop with java easier than with C(++).

Compiling
To compile the example (on linux, or just use a virtual machine to run linux: https://www.vagrantup.com)

You can now run the groovy script by calling it like any regular shell script:
(just remember to make it executable: chmod u+x)

./libgreet.groovy.sh

Mind the memory
Voila. Now if you do many calls or have very long running processes that require interop, you may need to investigate memory management. JNA has facilities to free memory by hand, which may or may not be required for interop with your target native library.

More information on JNA can be found here.