CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-net-java-dev-jna--jna

Java Native Access (JNA) provides Java programs easy access to native shared libraries without writing anything but Java code - no JNI or native code is required.

Pending
Overview
Eval results
Files

Java Native Access (JNA) 4.5.2

Java Native Access (JNA) provides Java programs easy access to native shared libraries 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.

Installation

// Maven dependency
<dependency>
    <groupId>net.java.dev.jna</groupId>
    <artifactId>jna</artifactId>
    <version>4.5.2</version>
</dependency>

Core Imports

import com.sun.jna.*;
import com.sun.jna.ptr.*;
import com.sun.jna.win32.*;

// Core classes
import com.sun.jna.Native;
import com.sun.jna.Library;
import com.sun.jna.Pointer;
import com.sun.jna.Memory;
import com.sun.jna.Structure;
import com.sun.jna.Function;
import com.sun.jna.NativeLibrary;

Basic Usage Example

import com.sun.jna.*;

// Define library interface
public interface CLibrary extends Library {
    CLibrary INSTANCE = Native.loadLibrary("c", CLibrary.class);
    
    /**
     * Print formatted string to stdout
     * @param format Format string
     * @param args Arguments for format string
     * @return Number of characters written
     */
    int printf(String format, Object... args);
    
    /**
     * Get length of string
     * @param s Null-terminated string
     * @return Length of string
     */
    int strlen(String s);
}

// Usage
CLibrary.INSTANCE.printf("Hello World\n");
int len = CLibrary.INSTANCE.strlen("Hello");

Architecture Overview

JNA is organized into several key components that work together to provide seamless Java-to-native interoperability:

Core Library Loading & Native Functions

  • Native - Central class for loading libraries and accessing native functionality
  • Library - Interface for defining native library mappings
  • Function - Represents pointers to native functions with invocation capabilities
  • NativeLibrary - Manages native library resources and function lookup

Memory Management & Pointers

  • Pointer - Base class for native memory access with type-safe operations
  • Memory - Heap-allocated native memory with automatic cleanup
  • PointerType - Base for custom pointer-based types

Structures & Type Mapping

  • Structure - Maps Java classes to C structs with automatic memory layout
  • Union - Represents C unions where fields share memory location
  • TypeMapper - Custom type conversion between Java and native types
  • NativeMapped - Interface for objects that can be converted to native types

Platform & Utilities

  • Platform - Cross-platform detection and information
  • WString - Wide character string support for Unicode
  • IntegerType/NativeLong - Platform-specific integer types

Key Capabilities

1. Core Library Loading & Native Functions

Load native libraries and call functions with automatic type conversion:

// Load library by name
MyLibrary lib = Native.loadLibrary("mylib", MyLibrary.class);

// Get native library instance for advanced usage  
NativeLibrary nativeLib = NativeLibrary.getInstance("mylib");
Function func = nativeLib.getFunction("my_function");

// Direct function invocation
Object result = func.invoke(String.class, new Object[]{"arg1", 42});

→ See Memory Management Documentation

2. Memory Management & Pointers

Safely allocate and access native memory:

// Allocate native memory
Memory buffer = new Memory(1024);

// Type-safe memory access
buffer.setInt(0, 42);
buffer.setString(4, "Hello", "UTF-8");

int value = buffer.getInt(0);
String text = buffer.getString(4, "UTF-8");

// Pointer arithmetic and sharing
Pointer shared = buffer.share(100, 200);  // Offset 100, size 200

→ See Memory Management Documentation

3. Structures & Type Mapping

Map Java classes to native structures:

public static class Point extends Structure {
    public int x, y;
    
    public Point() { super(); }
    public Point(int x, int y) {
        this.x = x;
        this.y = y;
        write();  // Write fields to native memory
    }
    
    @Override
    protected List<String> getFieldOrder() {
        return Arrays.asList("x", "y");
    }
}

// Usage
Point p = new Point(10, 20);
someNativeFunction(p);  // Pass by reference
p.read();  // Read updated values from native memory

→ See Structures & Types Documentation

4. Pass-by-Reference Parameters

Handle native functions that modify parameters using ByReference classes:

import com.sun.jna.ptr.*;

// Native function: int divide(int dividend, int divisor, int* quotient, int* remainder)
public interface MathLibrary extends Library {
    MathLibrary INSTANCE = Native.loadLibrary("mathlib", MathLibrary.class);
    
    int divide(int dividend, int divisor, 
               IntByReference quotient, IntByReference remainder);
}

// Usage
IntByReference quotient = new IntByReference();
IntByReference remainder = new IntByReference();

int result = MathLibrary.INSTANCE.divide(17, 5, quotient, remainder);
if (result == 0) {
    System.out.println("17 ÷ 5 = " + quotient.getValue() + " remainder " + remainder.getValue());
}

// Available reference types: IntByReference, LongByReference, ByteByReference,
// ShortByReference, FloatByReference, DoubleByReference, PointerByReference, etc.

→ See Pointer References Documentation

5. Windows Integration

Windows-specific functionality with stdcall support:

import com.sun.jna.win32.StdCallLibrary;
import com.sun.jna.win32.W32APIOptions;

public interface Kernel32 extends StdCallLibrary {
    Kernel32 INSTANCE = Native.loadLibrary("kernel32", Kernel32.class, 
                                         W32APIOptions.DEFAULT_OPTIONS);
    
    /**
     * Get current process ID
     * @return Current process ID
     */
    int GetCurrentProcessId();
    
    /**
     * Get handle to current process  
     * @return Handle to current process
     */
    Pointer GetCurrentProcess();
}

→ See Windows Integration Documentation

Native Class - Central Functionality

The Native class provides the core functionality for loading libraries and accessing native operations:

/**
 * Load a native library and create a Java interface proxy
 * @param name Library name (without extension)
 * @param interfaceClass Interface extending Library
 * @return Proxy instance implementing the interface
 */
public static <T extends Library> T loadLibrary(String name, Class<T> interfaceClass);

/**
 * Load library with custom options
 * @param name Library name
 * @param interfaceClass Interface class
 * @param options Map of library options
 * @return Proxy instance
 */
public static <T extends Library> T loadLibrary(String name, Class<T> interfaceClass, 
                                              Map<String, ?> options);

/**
 * Allocate native memory
 * @param size Number of bytes to allocate
 * @return Pointer to allocated memory
 */
public static long malloc(long size);

/**
 * Free native memory
 * @param ptr Pointer returned by malloc
 */
public static void free(long ptr);

// Constants
public static final int POINTER_SIZE;      // Size of native pointer (4 or 8 bytes)
public static final int WCHAR_SIZE;        // Size of wide character  
public static final boolean DEBUG_LOAD;    // Debug library loading
public static final boolean DEBUG_JNI;     // Debug JNI operations

Library Interface - Define Native Mappings

/**
 * Base interface for all native library mappings
 */
public interface Library {
    // Library options for customization
    String OPTION_TYPE_MAPPER = "type-mapper";
    String OPTION_FUNCTION_MAPPER = "function-mapper";
    String OPTION_INVOCATION_MAPPER = "invocation-mapper";
    String OPTION_STRUCTURE_ALIGNMENT = "structure-alignment";
    String OPTION_STRING_ENCODING = "string-encoding";
    String OPTION_ALLOW_OBJECTS = "allow-objects";
    String OPTION_CALLING_CONVENTION = "calling-convention";
    String OPTION_CLASSLOADER = "classloader";
    String OPTION_OPEN_FLAGS = "open-flags";
}

Platform Detection

/**
 * Platform information and detection utilities
 */
public final class Platform {
    // OS Type constants
    public static final int MAC = 0;
    public static final int LINUX = 1; 
    public static final int WINDOWS = 2;
    public static final int SOLARIS = 3;
    public static final int FREEBSD = 4;
    public static final int OPENBSD = 5;
    public static final int WINDOWSCE = 6;
    public static final int AIX = 7;
    public static final int ANDROID = 8;
    public static final int GNU = 9;
    public static final int KFREEBSD = 10;
    public static final int NETBSD = 11;
    
    // Current platform info
    public static final String ARCH;              // Current architecture
    public static final String C_LIBRARY_NAME;    // Standard C library name
    public static final String MATH_LIBRARY_NAME; // Math library name
    
    // Feature detection
    public static final boolean HAS_AWT;           // AWT support available
    public static final boolean HAS_BUFFERS;      // NIO Buffer support
    public static final boolean HAS_JAWT;         // Java AWT Native Interface
    public static final boolean HAS_DLL_CALLBACKS; // DLL callback support
    
    /**
     * Get current OS type constant
     * @return OS type constant (MAC, LINUX, WINDOWS, etc.)
     */
    public static int getOSType();
    
    /**
     * Check if running on macOS
     * @return true if macOS
     */
    public static boolean isMac();
    
    /**
     * Check if running on Linux
     * @return true if Linux
     */
    public static boolean isLinux();
    
    /**
     * Check if running on Windows
     * @return true if Windows
     */
    public static boolean isWindows();
    
    /**
     * Check if running on Android
     * @return true if Android
     */
    public static boolean isAndroid();
    
    /**
     * Check if 64-bit platform
     * @return true if 64-bit
     */
    public static boolean is64Bit();
    
    /**
     * Check if Intel/x86 architecture
     * @return true if Intel architecture
     */
    public static boolean isIntel();
    
    /**
     * Check if PowerPC architecture  
     * @return true if PowerPC
     */
    public static boolean isPPC();
    
    /**
     * Check if ARM architecture
     * @return true if ARM
     */
    public static boolean isARM();
}

Error Handling

/**
 * Exception thrown when native function returns error code
 */
public class LastErrorException extends RuntimeException {
    /**
     * Create exception with message
     * @param msg Error message
     */
    public LastErrorException(String msg);
    
    /**
     * Create exception with error code
     * @param code Native error code (errno or GetLastError)
     */
    public LastErrorException(int code);
    
    /**
     * Get the native error code
     * @return Error code from errno or GetLastError
     */
    public int getErrorCode();
}

Usage Patterns

Simple Library Interface

// Define interface
public interface MathLibrary extends Library {
    MathLibrary INSTANCE = Native.loadLibrary("m", MathLibrary.class);
    
    double sin(double x);
    double cos(double x);
    double sqrt(double x);
}

// Use library
double result = MathLibrary.INSTANCE.sin(Math.PI / 2);

Library with Options

Map<String, Object> options = new HashMap<>();
options.put(Library.OPTION_STRING_ENCODING, "UTF-8");
options.put(Library.OPTION_STRUCTURE_ALIGNMENT, Structure.ALIGN_DEFAULT);

MyLibrary lib = Native.loadLibrary("mylib", MyLibrary.class, options);

Function Pointer Usage

// Get function pointer from library
NativeLibrary lib = NativeLibrary.getInstance("mylib");
Function func = lib.getFunction("callback_setter");

// Create callback
Callback cb = new Callback() {
    public int callback(int value) {
        return value * 2;
    }
};

// Pass callback to native function
func.invoke(Void.class, new Object[]{cb});

Function Class - Direct Native Function Access

The Function class provides direct access to native function pointers with flexible invocation capabilities:

/**
 * Represents a pointer to a native function with invocation methods
 */
public class Function extends Pointer {
    // Call convention constants
    public static final int C_CONVENTION = 0;        // Standard C calling convention
    public static final int ALT_CONVENTION = 0x3F;   // Alternate convention (stdcall)
    public static final int THROW_LAST_ERROR = 0x40; // Throw exception on error
    public static final int USE_VARARGS = 0x180;     // Enable varargs support
    public static final int MAX_NARGS = 256;         // Maximum argument count
    
    /**
     * Get function from library by name (C convention)
     * @param libraryName Library containing the function
     * @param functionName Name of the function
     * @return Function instance
     */
    public static Function getFunction(String libraryName, String functionName);
    
    /**
     * Get function with specific calling convention
     * @param libraryName Library containing the function
     * @param functionName Name of the function  
     * @param callFlags Calling convention and options
     * @return Function instance
     */
    public static Function getFunction(String libraryName, String functionName, int callFlags);
    
    /**
     * Get function with encoding
     * @param libraryName Library containing the function
     * @param functionName Name of the function
     * @param callFlags Calling convention and options
     * @param encoding String encoding for parameters
     * @return Function instance
     */
    public static Function getFunction(String libraryName, String functionName, 
                                     int callFlags, String encoding);
    
    /**
     * Get function from native pointer address
     * @param functionAddress Native address of function
     * @return Function instance
     */
    public static Function getFunction(Pointer functionAddress);
    
    /**
     * Get function from native pointer with options
     * @param functionAddress Native address of function  
     * @param callFlags Calling convention and options
     * @return Function instance
     */
    public static Function getFunction(Pointer functionAddress, int callFlags);
    
    /**
     * Invoke function with return type and arguments
     * @param returnType Expected return type
     * @param args Function arguments
     * @return Result converted to return type
     */
    public Object invoke(Class<?> returnType, Object[] args);
    
    /**
     * Invoke function with options
     * @param returnType Expected return type
     * @param args Function arguments
     * @param options Invocation options
     * @return Result converted to return type
     */
    public Object invoke(Class<?> returnType, Object[] args, Map<String, ?> options);
    
    /**
     * Invoke using reflection method information
     * @param method Method providing signature information
     * @param parameterTypes Expected parameter types
     * @param returnType Expected return type
     * @param args Function arguments
     * @param options Invocation options
     * @return Result converted to return type
     */
    public Object invoke(Method method, Class<?>[] parameterTypes, Class<?> returnType,
                        Object[] args, Map<String, ?> options);
    
    /**
     * Get function name
     * @return Function name or address string
     */
    public String getName();
    
    /**
     * Get calling convention flags
     * @return Calling convention and option flags
     */
    public int getCallingConvention();
    
    // Type-specific invocation methods
    public void invokeVoid(Object[] args);
    public int invokeInt(Object[] args);
    public long invokeLong(Object[] args);
    public float invokeFloat(Object[] args);
    public double invokeDouble(Object[] args);
    public Pointer invokePointer(Object[] args);
    public String invokeString(Object[] args);
}

Function Usage Examples

// Direct function access with different return types
Function strlen = Function.getFunction("c", "strlen");
int length = (Integer) strlen.invoke(Integer.class, new Object[]{"Hello"});

Function malloc = Function.getFunction("c", "malloc");
Pointer memory = (Pointer) malloc.invoke(Pointer.class, new Object[]{1024L});

Function free = Function.getFunction("c", "free");
free.invoke(Void.class, new Object[]{memory});

// Windows stdcall function
Function messageBox = Function.getFunction("user32", "MessageBoxA", Function.ALT_CONVENTION);
int result = (Integer) messageBox.invoke(Integer.class, 
    new Object[]{Pointer.NULL, "Hello World", "Title", 0});

// Function with error checking
Function openFile = Function.getFunction("kernel32", "CreateFileA", 
                                       Function.ALT_CONVENTION | Function.THROW_LAST_ERROR);
try {
    Pointer handle = (Pointer) openFile.invoke(Pointer.class, 
        new Object[]{"test.txt", 0x40000000, 0, null, 3, 0, null});
} catch (LastErrorException e) {
    System.err.println("Failed to open file: " + e.getMessage());
}

Sub-Documentation

Version Information

// JNA version constants (internal)
String JNA_VERSION = "4.5.2";        // Library version
String NATIVE_VERSION = "5.0.1";     // Native library version

This documentation provides comprehensive coverage of JNA's API for seamless Java-to-native interoperability without requiring JNI knowledge or native code development.

Install with Tessl CLI

npx tessl i tessl/maven-net-java-dev-jna--jna
Workspace
tessl
Visibility
Public
Created
Last updated
Describes
mavenpkg:maven/net.java.dev.jna/jna@4.5.x
Publish Source
CLI
Badge
tessl/maven-net-java-dev-jna--jna badge