Java Native Access (JNA) is a community-developed library that provides Java programs easy access to native shared libraries without using the Java Native Interface (JNI). JNA's design aims to provide native access in a natural way with a minimum of effort. Unlike JNI, no boilerplate or generated glue code is required.
Architecture
The JNA library uses a small native library called foreign function interface library (libffi) to dynamically invoke native code. The JNA library uses native functions allowing code to load a library by name and retrieve a pointer to a function within that library, and uses libffi library to invoke it, all without static bindings, header files, or any compile phase. The developer uses a Java interface to describe functions and structures in the target native library. This makes it quite easy to take advantage of native platform features without incurring the high development overhead of configuring and building JNI code.
Note: The meaning of TCHAR changes between char and wchar_t according to some preprocessor definitions. LPCTSTR follows.
Memory byte alignment for data structures
Native libraries have no standardized memory byte alignment flavor. JNA defaults to an OS platform specific setting, that can be overridden by a library specific custom alignment. If the alignment details are not given in the documentation of the native library, the correct alignment must be determined by trial and error during implementation of the Java wrapper.
Example
The following program loads the local C standard library implementation and uses it to call the printf function.
Note: The following code is portable and works the same on Windows and POSIX (Linux / Unix / macOS) platforms.
importcom.sun.jna.Library;importcom.sun.jna.Native;importcom.sun.jna.Platform;/** Simple example of native library declaration and usage. */publicclassHelloWorld{publicinterfaceCLibraryextendsLibrary{CLibraryINSTANCE=(CLibrary)Native.loadLibrary((Platform.isWindows()?"msvcrt":"c"),CLibrary.class);voidprintf(Stringformat,Object...args);}publicstaticvoidmain(String[]args){CLibrary.INSTANCE.printf("Hello, World\n");for(inti=0;i<args.length;i++){CLibrary.INSTANCE.printf("Argument %d: %s\n",i,args[i]);}}}
The following program loads the C POSIX library and uses it to call the standard mkdir function.
Note: The following code is portable and works the same on POSIX standards platforms.
importcom.sun.jna.Library;importcom.sun.jna.Native;/** Simple example of native C POSIX library declaration and usage. */publicclassExampleOfPOSIX{publicinterfacePOSIXextendsLibrary{publicintchmod(Stringfilename,intmode);publicintchown(Stringfilename,intuser,intgroup);publicintrename(Stringoldpath,Stringnewpath);publicintkill(intpid,intsignal);publicintlink(Stringoldpath,Stringnewpath);publicintmkdir(Stringpath,intmode);publicintrmdir(Stringpath);}publicstaticvoidmain(String[]args){// It is possible to load msvcrt for its partial POSIX support on Windows...POSIXposix=(POSIX)Native.loadLibrary("c",POSIX.class);// but it will still fail on Windows due to /tmp being missing.posix.mkdir("/tmp/newdir",0777);posix.rename("/tmp/newdir","/tmp/renamedir");}}
The program below loads the Kernel32.dll and uses it to call the Beep and Sleep functions.
Note: The following code works only on Windows platforms.
importcom.sun.jna.Library;importcom.sun.jna.Native;/** Simple example of Windows native library declaration and usage. */publicclassBeepExample{publicinterfaceKernel32extendsLibrary{// FREQUENCY is expressed in hertz and ranges from 37 to 32767// DURATION is expressed in millisecondspublicbooleanBeep(intFREQUENCY,intDURATION);publicvoidSleep(intDURATION);}publicstaticvoidmain(String[]args){Kernel32lib=(Kernel32)Native.loadLibrary("kernel32",Kernel32.class);lib.Beep(698,500);lib.Sleep(500);lib.Beep(698,500);}}
Performance
Benchmarks show JNA averages ten times slower than JNI.[3][4][5]
Alternatives
Several alternatives are emerging.[6] The tradeoff between easy to implement the code and runtime speed should be considered when evaluating these software development tools. The addition of third party dependent libraries that must be redistributed and updated is another factor in the decision of which tool to use. The Technology readiness level should also be considered.