Java Native Access

Source: Wikipedia, the free encyclopedia.
Java Native Access
Original author(s)Todd Fast, Timothy Wall, Liang Chen
Initial releaseMay 9, 2007 (2007-05-09)
Stable release
5.14.0 / December 10, 2023; 4 months ago (2023-12-10)[1]
Repository
Written in
LGPL version 2.1 or later and (from version 4.0 onward) the Apache Software License, version 2.0
Websitegithub.com/java-native-access/jna

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

JNI
code.

JNA is built and tested on

. It is also possible to tweak and recompile the native build configurations to make it work on most other platforms that run Java.

Mapping types

The following table shows an overview of types mapping between Java and native code and supported by the JNA library.[2]

Native Type Size Java Type Common Windows Types
char 8-bit integer byte BYTE, TCHAR
short
16-bit integer
short
WORD
wchar_t 16/32-bit character char TCHAR
int 32-bit integer int DWORD
int boolean value boolean BOOL
long
32/64-bit integer NativeLong LONG
long long
64-bit integer
long
__int64
float
32-bit FP
float
double
64-bit FP
double
char* C string String LPCSTR
void* pointer Pointer LPVOID, HANDLE, LPXXX

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.

import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Platform;

/** Simple example of native library declaration and usage. */
public class HelloWorld {
    public interface CLibrary extends Library {
        CLibrary INSTANCE = (CLibrary) Native.loadLibrary(
            (Platform.isWindows() ? "msvcrt" : "c"), CLibrary.class);
        void printf(String format, Object... args);
    }

    public static void main(String[] args) {
        CLibrary.INSTANCE.printf("Hello, World\n");
        for (int i = 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.

import com.sun.jna.Library;
import com.sun.jna.Native;

/** Simple example of native C POSIX library declaration and usage. */
public class ExampleOfPOSIX {
    public interface POSIX extends Library {
	    public int chmod(String filename, int mode);
	    public int chown(String filename, int user, int group);
	    public int rename(String oldpath, String newpath);
	    public int kill(int pid, int signal);
	    public int link(String oldpath, String newpath);
	    public int mkdir(String path, int mode);
	    public int rmdir(String path);
    }

    public static void main(String[] args) {
        // It is possible to load msvcrt for its partial POSIX support on Windows...
        POSIX posix = (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.

import com.sun.jna.Library;
import com.sun.jna.Native;

/** Simple example of Windows native library declaration and usage. */
public class BeepExample {
    public interface Kernel32 extends Library {
        // FREQUENCY is expressed in hertz and ranges from 37 to 32767
        // DURATION is expressed in milliseconds
        public boolean Beep(int FREQUENCY, int DURATION);
        public void Sleep(int DURATION);
    }

    public static void main(String[] args) {
	    Kernel32 lib = (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.

See also

References

  1. ^ "Release 5.14.0". GitHub. 2023-01-14.
  2. ^ "Default Type Mappings". jna.dev.java.net. Retrieved 2011-08-02.
  3. ^ "JNI vs JNA performance". Reddit. Retrieved 30 March 2023.
  4. ^ "JNI vs JNA benchmark". Medium. Retrieved 30 March 2023.
  5. ^ "JNI vs JNA performance benchmark". Stack Overflow. Stack Overflow. Retrieved 30 March 2023.
  6. ^ "JNI alternatives emerging". OKTA. Retrieved 30 March 2023.

External links