JNA API 3.0.5

JNA API Documentation

This document is the API specification for the JNA library for simplified native library access for Java.

See:
          Description

Java Native Access
com.sun.jna Provides simplified native library access.
com.sun.jna.ptr Provides various native pointer-to-type (<type> *) representations.
com.sun.jna.win32 Provides type and function mappers required for standard APIs on the Windows platform.

 

Examples
com.sun.jna.examples Various examples of library mappings and cross-platform feature implementations.
com.sun.jna.examples.dnd Cross-platform ghosted drag image implementation with demo application.

 

Unix Examples
com.sun.jna.examples.unix Provides examples of *nix library mappings.

 

Windows Examples
com.sun.jna.examples.win32 Provides examples of w32 library mappings.

 

This document is the API specification for the JNA library for simplified native library access for Java.

Top  JNA Home  API w/FRAMES 

Java Native Access (JNA)

JNA provides simplified access to native library methods without requiring any additional JNI or native code.

Table of Contents

Top

Library Mapping

When you've determined which shared library holds the methods to which you need access, create an interface class corresponding to that library. For example, a mapping for the C library itself would look like this:
public interface CLibrary extends Library {
    CLibrary INSTANCE = (CLibrary)Native.loadLibrary("c", CLibrary.class);
}
The String passed to the Native.loadLibrary method is the undecorated name of the shared library file. Here are some examples of library name mappings.

OSLibrary NameString
Windowsuser32.dlluser32
LinuxlibX11.soX11
Mac OS Xlibm.dylibm

Any given native library with a unique filesystem path is represented by a single instance of NativeLibrary and obtained via NativeLibrary.getInstance(String). The native library will be unloaded when no longer referenced by any Java code.

The search path for loaded native libraries may be modified by setting jna.library.path. See NativeLibrary for details.

Table of Contents

Function Mapping

Function names are mapped directly from their Java interface name to the symbol exported by the native library. For instance, the function to convert an ASCII string into an integer would look like this:
public interface CLibrary extends Library {
    int atol(String s);
}
If you prefer to rename the Java methods to conform to Java coding conventions, then you can provide an entry (Library.OPTION_FUNCTION_MAPPER/FunctionMapper) in the options Map passed to Native.loadLibrary() which maps the Java names to the native names. While this keeps your Java code a little cleaner, the additional mapping of names may make it a little less obvious the native functions being called.

An instance of the Function class is obtained through the NativeLibrary instance corresponding to the containing native library. This Function instance handles argument marshalling and delegation to the native function.

Table of Contents

Marshalling/Unmarshalling (Java/Native Type Conversions)

Java types must be chosen to match native types of the same size. Following are the types supported by the JNA library.

Java TypeC TypeNative Representation
booleanint32-bit integer (customizable)
bytechar8-bit integer
charwchar_tplatform-dependent
shortshort16-bit integer
intint32-bit integer
longlong long, __int6464-bit integer
floatfloat32-bit floating point
doubledouble64-bit floating point
Buffer
Pointer
pointerplatform-dependent (32- or 64-bit pointer to memory)
<T>[] (array of primitive type)pointer
array
32- or 64-bit pointer to memory (argument/return)
contiguous memory (struct member)
In addition to the above types, which are supported at the native layer, the JNA Java library automatically handles the following types. All but NativeMapped and NativeLong are converted to Pointer before being passed to the native layer.
Stringchar*NUL-terminated array (native encoding or jna.encoding)
WStringwchar_t*NUL-terminated array (unicode)
Structurestruct*
struct
pointer to struct (argument or return) (or explicitly)
struct by value (member of struct) (or explicitly)
Unionunionsame as Structure
Structure[]struct[]array of structs, contiguous in memory
Callback<T> (*fp)()function pointer (Java or native)
NativeMappedvariesdepends on definition
NativeLonglongplatform-dependent (32- or 64-bit integer)
PointerTypepointersame as Pointer

NOTES

Primitive Arrays

Java primitive arrays may be used wherever a native primitive array is used. Any changes made by the native code to an array during a function call will be reflected in the Java array. If the native code will use the array outside of the function call where the array is provided, Memory or Buffer should be used instead (see Buffers).

To map a native multi-dimensional array, use a single-dimensional Java array with a number of elements equivalent to the full native array, e.g.

// Original C code
#define DIM0 2
#define DIM1 3
int array[DIM0][DIM1];
int i,j;

for (i=0;i < DIM0;i++) {
  for (j=0;j < DIM1;j++) {
    array[i][j] = i*DIM1 + j;
  }
}

// Equivalent JNA code
final int DIM0 = 2;
final int DIM1 = 3;
int[] array = new int[6];
for (int i=0;i < DIM0;i++) {
  for (int j=0;j < DIM1;j++) {
    array[i*DIM1 + j] = i*DIM1 + j;                   
  }                   
}

Pointers

Pointers may be used as an opaque type from which other data types may be extracted. The Pointer type is a reasonable fallback for any pointer-based type (including arrays). The user is generally not allowed to construct a Pointer de novo.

Type-safe pointers may be defined by deriving from the PointerType class. Any such user-defined type will be treated the same as a Pointer.

Strings

Java Strings perform the same function as the native types const char* and const wchar_t* (NUL-terminated arrays). In order to use the proper type when calling a native function, we have to introduce some sort of annotation to identify how the java String should be converted. Java Strings are normally converted to char* since this is the most common usage of strings. Strings are automatically converted to a NUL-terminated array of char across the function call. Returned char* values are automatically copied into a String if the method signature returns String (strdup, for example).

If the native method returns char* and actually allocates memory, a return type of Pointer should be used to avoid leaking the memory. It is then up to you to take the necessary steps to free the allocated memory.

When converting Java unicode characters into an array of char, the default platform encoding is used, unless the system property jna.encoding is set to a valid encoding. This property may be set to "UTF8", for example, to ensure all native strings use that encoding.

Wide Strings

The WString class is used to identify wide character strings. Unicode values are copied directly from the Java char array to a native wchar_t array.

Buffers/Memory Blocks

Use arrays to represent buffers of primitive types passed to a function for use only during the function invocation. A native method cannot return a Java array, since there is no canonical way to indicate the intended length of the returned array. Instead, use one of the array access methods in the Pointer class, supplying the length of the returned array.

Buffers may also be used as a memory buffer input argument; direct byte buffers can often provide much improved performance over primitive arrays. A pointer provided by native code may be converted to a Buffer by calling Pointer.getByteBuffer(long, long).

If you need to pass in a subset of a primitive array, you can do so by wrapping it in a Buffer subclass, such as ByteBuffer, using the ByteBuffer.wrap(byte[],int,int) method. Wrapping an array in a buffer also allows you to pass only a subset of a Java array to the native function.

Callbacks (Function Pointers)

JNA supports supplying Java callbacks to native code. You must define an interface that extends the Callback interface, and define a single callback method with a signature that matches the function pointer required by the native code. The name of the method must be "callback", and the arguments and return value follow the same rules as for a direct function invocation.

If your native code initializes function pointers within a struct, JNA will automatically generate an Callback instance matching the declared type. This enables you to easily call the function supplied by native code using proper Java syntax.

// Original C code
struct _functions {
  int (*open)(const char*,int);
  int (*close)(int);
};

// Equivalent JNA mapping
public class Functions extends Structure {
  public static interface OpenFunc extends Callback {
    int callback(String name, int options);
  }
  public static interface CloseFunc extends Callback {
    int callback(int fd);
  }
  public OpenFunc open;
  public CloseFunc close;
}
...
Functions funcs = new Functions();
lib.init(funcs);
int fd = funcs.open.callback("myfile", 0);
funcs.close.callback(fd);
Callbacks may also be used as return values. Native function pointers are wrapped in a proxy implementing the declared Callback type, to facilitate calling from Java.
// Original C code
typedef void (*sig_t)(int);
sig_t signal(int signal, sig_t sigfunc);

// Equivalent JNA mapping
public interface CLibrary extends Library {
    public interface SignalFunction extends Callback {
        void callback(int signal);
    }
    SignalFunction signal(int signal, SignalFunction func);
}

Varargs

The C varargs function definition may be mapped to a Java varargs method definition. For example,
// Original C code
extern int printf(const char* fmt, ...);

// Equivalent JNA mapping
interface CLibrary extends Library {
    int printf(String fmt, ...);
}

Structures

The Java Structure represents a native struct. By default, this type is treated as a pointer to structure (struct *) on the native side when used as a parameter or return value. When used as a structure field, the structure is interpreted as by value. To force the complementary interpretation, the tagging interfaces Structure.ByValue and Structure.ByReference are provided.

Pointer-to-Structure Arguments

To pass a pointer to a structure as an argument, simply use the Java structure subclass, and a pointer to native data memory will be used. The contents of the structure will be passed to the function and updated when the function returns. Structures are packed according to the default alignment rules for the platform's native C structs.
// Original C code
typedef struct _Point {
  int x, y;
} Point;

Point* translate(Point* pt, int dx, int dy);

// Equivalent JNA mapping
class Point extends Structure { public int x, y; }
Point translate(Point pt, int x, int y);
...
Point pt = new Point();
Point result = translate(pt, 100, 100);

Structure by Value Arguments/Return

To pass a structure by value, first define the structure, then define an empty class from that which implements Structure.ByValue. Use the ByValue class as the argument or return type.

// Original C code
typedef struct _Point {
  int x, y;
} Point;

Point translate(Point pt, int dx, int dy);

// Equivalent JNA mapping
class Point extends Structure {
    public static class ByValue extends Point implements Structure.ByValue { }
    public int x, y;
}
Point.ByValue translate(Point.ByValue pt, int x, int y);
...
Point.ByValue pt = new Point.ByValue();
Point result = translate(pt, 100, 100);

Array-of-Structure Arguments

To pass an array of structures, simply use a Java array of the desired structure type. If the array is uninitialized, it will be auto-initialized prior to the function call.

// Original C code
void get_devices(struct Device[], int size);

// Equivalent JNA mapping
int size = ...
Device[] devices = new Device[size];
lib.get_devices(devices, devices.length);
Alternatively, you can reallocate a single Structure instance into an array as follows:
Device dev = new Device();
// As an array of Structure
Structure[] structs = dev.toArray(size);
// As an array of Device
Device[] devices = (Device[])dev.toArray(size);

Returning an Array of struct

Declare the method as returning a Structure of the appropriate type, then invoke Structure.toArray(int) to convert to an array of initialized structures of the appropriate size. Note that your Structure class must have a no-args constructor, and you are responsible for freeing the returned memory if applicable in whatever way is appropriate for the called function.

// Original C code
struct Display* get_displays(int* pcount);
void free_displays(struct Display* displays);

// Equivalent JNA mapping
Display get_displays(IntByReference pcount);
void free_displays(Display[] displays);
...
IntByReference pcount = new IntByReference();
Display d = lib.get_displays(pcount);
Display[] displays = (Display[])d.toArray(pcount.getValue());
...
lib.free_displays(displays);

Nested Structure Definitions

Nested structures are treated as consecutive memory (as opposed to pointers to structures). For example:
// Original C code
typedef struct _Point {
  int x, y;
} Point;

typedef struct _Line {
  Point start;
  Point end;
} Line;

// Equivalent JNA mapping
class Point extends Structure {
  public int x, y;
}

class Line extends Structure {
  public Point start;
  public Point end;
}
Explicit initialization of nested structures is not required; the objects will be created as needed and properly mapped to the parent structure's memory.

If you need a pointer to a structure within your structure, you can use the Structure.ByReference tagging interface to indicate the field should be treated as a pointer instead of inlining the full structure.

// Original C code
typedef struct _Line2 {
  Point* p1;
  Point* p2;
} Line2;

// Equivalent JNA mapping
class Point extends Structure {
    public static class ByReference extends Point implements Structure.ByReference { }
    public int x, y;
}
class Line2 extends Structure {
  public Point.ByReference p1;
  public Point.ByReference p2;
}
The more general case is just a pointer to memory. This allows you to define the field without necessarily defining the inner structure itself, similar to declaring a struct without defining it in C:
// Original C code
typedef struct _Line2 {
  Point* p1;
  Point* p2;
} Line2;

// Equivalent JNA mapping
class Line2 extends Structure {
  public Pointer p1;
  public Pointer p2;
}

Line2 line2;
Point p1, p2;
...
line2.p1 = p1.getPointer();
line2.p2 = p2.getPointer();

Nested arrays

Structures with nested arrays require an explicit constructor to ensure the structure size is properly calculated.
typedef struct _Buffer {
  char buf1[32];
  char buf2[1024];
} Buffer;

class Buffer extends Structure {
  public byte[] buf1 = new byte[32];
  public byte[] buf2 = new byte[1024];
}
Calculation of the native size of the structure is deferred until the structure is actually used.

Variable-sized structures

Structures with variable size, or with primitive array elements, for example:
// Original C code
typedef struct _Header {
  int flags;
  int buf_length;
  char buffer[1];
} Header;
require a constructor which establishes the required size for the structure and initializes things appropriately. For example:
// Equivalent JNA mapping
class Header extends Structure {
  public int flags;
  public int buf_length;
  public byte[] buffer;
  public Header(int bufferSize) {
    buffer = new byte[bufferSize];
    buf_length = buffer.length;
    allocateMemory();
  }
}

Volatile fields

Normally, JNA will write the entire contents of a Structure prior to a function call and read back from native memory after the function call. Sometimes a structure field is not intended for client use, gets modified asynchronously by hardware, or otherwise is effectively read-only. If you expect any fields of the structure to be modified by any agent outside your Java program, you should mark the field volatile. This prevents JNA from automatically updating the native memory from the Java value. You can still force an update of the native memory from the Java value by calling Structure.writeField(String) for the field in question.
class Data extends com.sun.jna.Structure {
  public volatile int refCount;
  public int value;
}
...
Data data = new Data();
In the above example, the field refCount will only be written to native memory based on the Java value with a call to data.writeField("refCount"). To obtain the current state of native memory, call Structure.read() (to update the entire structure) or data.readField("refCount") (to update just the refCount field).

Read-only fields

If you want to absolutely prevent Java code from modifying a Structure's contents, you may mark its fields final. Structure reads can still overwrite the values based on native memory contents, but no Java code will be able to modify any of the fields.
class ReadOnly extends com.sun.jna.Structure {
  // Do not initialize the field here, or the compiler will inline the value!
  public final int refCount;
  {
    // Initialize fields here, to ensure the values are not inlined
    refCount = -1;
    read();
    // refCount might now have a different value
  }
}
...
ReadOnly ro = new ReadOnly();
// Will not compile!
ro.refCount = 0;
Make certain you attend to the following:
  1. All final fields should be initialized in the constructor.
  2. If you call Structure.read() from anywhere but the constructor, keep in mind that the compiler and/or hotspot will be assuming field values will not change across that function call.

Unions

Unions are a special type of Structure. Each declared field within the union overlays the same space in native memory. When writing a union to native memory, you must specify which field is to be written by supplying the desired field's class to the Union.setType(java.lang.Class) method. On read, all non-pointer-based fields will be initialized from native memory. Structure, String, and WString members will not be initialized unless they are selected via Union.setType(java.lang.Class).

Java Object arguments

In some cases, it would seem convenient to pass a Java object as an opaque pointer for later use by a Java callback method. Unfortunately, this proves problematic in that the native code must become responsible for reference tracking. Until a consistent method or methods of handling these situations is formulated, passing Java objects directly is not supported.

Table of Contents

Invocation Mapping

Sometimes native functions exist only as C preprocessor macros or as inline functions. If you need to do more than simply change the name of the invoked function (which can be handled via Function Mapping), an InvocationMapper allows you to arbitrarily reconfigure the function invocation, including changing the method name and reordering, adding, or removing arguments. See the InvocationMapper documentation for details.

Table of Contents

Library Global Data

The method NativeLibrary.getGlobalVariableAddress(java.lang.String) may be used to obtain the address of global variables as a Pointer. Pointer methods may then be used to read or write the value as appropriate for the variable type.

Table of Contents

VM Crash Protection

It is not uncommon when defining a new library and writing tests to encounter memory access errors which crash the VM. These are often caused by improper mappings or invalid arguments passed to the native library. To generate Java errors instead of crashing the VM, call Native.setProtected(true).


JNA API 3.0.5

Copyright © 2007-2008 Timothy Wall. All Rights Reserved.