Java Native Access (JNA)JNA provides Java programs easy access to native shared libraries (DLLs on Windows) without writing anything but Java code—no JNI or native code is required. This functionality is comparable to Windows' Platform/Invoke and Python's ctypes. Access is dynamic at runtime without code generation.
JNA's design aims to provide native access in a natural way with a minimum of effort. No boilerplate or generated code is required. While some attention is paid to performance, correctness and ease of use take priority.
The JNA library uses a small native library stub to dynamically invoke native code. 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 overhead of configuring and building JNI code for multiple platforms.
This library is provided under the LGPL, version 2.1 or later.
NOTE: Sun is not sponsoring this project, even though the package name (
com.sun.jna) might imply otherwise.
Bufferarguments (primitive types and pointers) as pointer-to-buffer
longsupport (32- or 64-bit as appropriate)
Java Native Access (JNA) has a single component,
jna.jar; the supporting native library (
jnidispatch) is included in the jar file. JNA is capable of extracting and loading the native library on its own, so you don't need additional configuration. JNA falls back to extraction if the native library is not already installed on the local system somewhere accessible to
System.loadLibrary (see information on library loading). The native library is also available in platform-specific jar files for use with Java Web Start.
jna.jarfrom the download page.
printffunction from the standard C library and calls it. Be sure to include jna.jar in the classpath:
jna.library.pathsystem property to the path to your target library. This property is similar to
java.library.pathbut only applies to libraries loaded by JNA.
Libraryinterface. Following is an example of mapping for the Windows kernel32 library.
Native.loadLibrary(Class)method, providing the native library interface you defined in step (5).
Mapof options may be provided as the third argument to
loadLibraryto customize the library behavior; some of these options are explained in more detail below.
Structureand add public fields (which may include arrays or nested structures).
Unsigned types use the same mappings as signed types. A full list of mappings may be found here.
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 float 32-bit FP float double 64-bit FP double char* C string String LPTCSTR void* pointer Pointer LPVOID, HANDLE, LPXXX
structs) are represented by their corresponding Java types. For example:
Arrays of C strings (the
char* argv to the C
main, for example), may be represented by
String in Java code.
struct, a Java Structure should be used. If the
structis passed or returned by value, you need only make minor modifications to the parameter or return type class declaration.
Typically you define a
public static class derived from
Structure within your library interface definition. This allows the structure to share any options (like custom type mapping) defined for the library interface.
If a function requires an array of
struct, a Java
Structure may be used. When passing in an array of
Structure, it is not necessary to initialize the array elements (the function call will allocate, zero memory, and assign the elements for you). If you do need to initialize the array, you should use the
Structure.toArray method to obtain an array of
Structure elements contiguous in memory, which you can then initialize as needed.
Unions are generally interchangeable with
Structures, but require that you indicate which union field is active with the
setType method before it can be properly passed to a function call.
ByReferencetypes to capture the returned value, or subclass your own. For example:
Alternatively, you could use a Java array with a single element of the desired type, but the
ByReferenceconvention better conveys the intent of the code.
Pointer class provides a number of accessor methods in addition to
getByteArray() which effectively function as a typecast onto the memory.
Type-safe pointers may be declared by deriving from the
TypeMapperinstance is passed as the value for the TYPE_MAPPER key in the options map passed to
Alternatively, user-defined types may implement the NativeMapped interface, which determines conversion to and from native types on a class-by-class basis.
You may also customize the mapping of Java method names to the corresponding native function name. The StdCallFunctionMapper is one implementation which automatically generates
stdcall-decorated function names from a Java interface method signature. The mapper should be passed as the value for the OPTION_FUNCTION_MAPPER key in the options map passed to the
Refer to this table in the overview for a complete list of built-in type mappings.
callbackmethod. Callbacks are implemented by wrapping a Java object method in a little bit of C glue code. The simplest usage resembles using anonymous inner classes to register event listeners. Following is an example of callback usage:
Here is a more involved example, using the w32 APIs to enumerate all native windows:
If your callback needs to live beyond the method invocation where it is used, make sure you keep a reference to it or the native code will call back to an empty stub after the callback object is garbage collected.
Proxy wrappers are automatically generated for function pointers found within structs initialized by native code. This facilitates calling those functions from Java.
Here's a brief example of using JNA from JRuby:
The native code is expecting a fixed-size buffer, which it will fill in with the requested data. A Java
// Returns the number of characters written to the buffer int getString(char* buffer, int bufsize);
Stringis not appropriate here, since
Strings are immutable. Nor is a Java
StringBuffer, since the native code only fills the buffer and does not change its size. The appropriate argument type would be either
Memory, or an NIO
Buffer, with the size of the object passed as the second argument. The method Native.toString(byte) may then be used to convert the array of byte into a Java
On Windows, you can use a Java
int, since the native
long type is always 32 bits. On any other platform, the type may be 32 or 64 bits, so you should use the NativeLong type to ensure the proper size is used.
stdcallcalling convention, your interface should extend the
StdCallLibraryinterface. Using the wrong calling convention for a library will usually cause a VM crash.
Structure, it will print each defined field with its calculated memory offset. If when launching the VM, you pass it "-Djna.dump_memory=true",
toStringwill also dump the contents of the corresponding native memory. This is useful to determine if you've added or omitted a field, or chosen an incorrect size. Viewing the memory as bytes usually makes it clear where field boundaries should be, assuming the memory has been initialized by native code.
Windows Mobile is supported by libffi (mingwce) but JNA has not yet been (publicly) built for that target. Nothing technically should prevent it, though.
A simple test calling a function like
int testfunc(int) with JNA
might take an order of magnitude (~10X) greater time than equivalent custom
JNI (whether it actually does in the context of your application is a
This magnitude is typical of the difference between systems using
dynamically-maintained type information and systems where type information is
statically compiled. JNI hard-codes type information in the method
invocation, where JNA dynamically determines type information at runtime.
You might expect a speedup of about an order of magnitude moving to custom JNI, but the actual difference will vary depending on usage and function signatures. As with any optimization process, you should determine first where you need a speed increase, and then see how much difference there is by performing targeted optimizations. The ease of programming everything in Java usually outweighs performance gains when using custom JNI.
Java primitive arrays are generally slower to use than memory (Pointer, Memory, or ByReference) or NIO buffers, since the Java memory has to be pinned and possibly copied across the native call, since the Java array is not necessarily contiguously allocated.
com.sun.jna.examplespackage are some examples of using the JNA library (and are pretty nifty utilities in and of themselves).
Please use the appropriate mailing list to ask for help, suggest ideas, contribute patches, etc. All contributions are welcome. When asking about how to do a library mapping, be sure to include C API definitions and example usage, as well as whatever Java mapping you've already tried.
All mailing lists are also available via RSS:
The library works fairly well now, but there are a number of tasks with which we'd appreciate help:
jnidispatchlibrary backend on new platforms (it should mostly work out of the box if we can just get access to the appropriate build platform).
user32on Windows. This is important not for having an exhaustive library definition but to illustrate all the different ways a native library may need to be mapped.
If you want to do a build yourself, you'll need ANT, GNU make and GCC. On windows, you will need either cygwin GCC or the MINGW32 version (MSVC will
build most of the JNA native library, but will not build the
library and chokes on the libffi includes). To rebuild
jna.jar, and run the unit tests, do
% ant dist test
If JNA has not yet been built on for your platform, you may need to tweak the build.xml and native/Makefile build configurations so that your platform is recognized.
The project also includes NetBeans and Eclipse project configurations, if you're so inclined.
Fragments of this project date back to a small shared stubs library originally written by Sheng Liang of the Sun JNI team and demoed at JavaOne circa 1999.
Todd Fast (also of Sun) first published JNA on dev.java.net in the fall of 2006, which allowed calls with primitive type parameters and partial struct support (that code is still available in the SVN repo under the CVS HEAD tag). From the original project announcement:
Headline Initial JNA code checked in Date Nov 30, 2006 Contributed by toddfastAnnouncement
Thanks everyone for your interest in the Java Native Access (JNA) project! I've just checked in the initial code. I've worked on this little project off-and-on for the better part of 6-7 years, and this release comes about a year after I last looked at it. Therefore, I'm only just now getting familiar with it again after refactoring and redesigning for JDK 5 last year, so there may be any number of issues or shortcomings leftover since my last time with it. Please look through the code and get involved!
The Java library code is contained in a NetBeans 5.x project. If you want to build it, please use NetBeans or use the Ant build script in the root of the jnalib/ directory. I will upload a binary at some point to make it a bit easier to get started.
I've checked in binaries of the jnidispatch library and the testlib library for Win32 (.dll's), but don't have convenient access to build these for other platforms. I would greatly appreciate help from others to compile and test versions for other platforms, particularly Mac OS.
To get an idea how to use JNA, please refer to the JUnit tests in the test/ directory. These are crufty and not meant to be examples, but will have to suffice until real samples are available (I would definitely appreciate community help with those as well). Note that you will need to modify your java.library.path system property to include the jnidispatch binary (and possibly the testlib binary) in order to use JNA or run the unit tests. For example: java -Djava.library.path=./native/testlib/Debug;./native/jnidispatch/Debug ...
Timothy Wall rebooted the project in February of 2007, introducing a number of critical features, adding linux and OSX ports, and making the library usable with more than just rudimentary functions. I was looking for a way to experiment with native libraries without having to carve out a new Makefile and build process (those of you who've never built multi-lingual projects involving C don't know what you're missing). Specifically I wanted some shaped windows and better file system access. After a few proof-of-concept tests, I scouted around for existing projects from which I could bootstrap (see the OTHERS file for some of the projects that are out there). JNA had the simplest, most straightforward architecture (as did NLINK, which likely had the same roots). It was also the least problematic to make work cross-platform with a consistent build process.
Wayne Meissner has contributed enormously ("a metric buttload of hard work") in getting libffi and the various additional native libraries working. His work on a Java interface to the gstreamer library has contributed a number of critical features to JNA.