or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.mdmemory-management.mdptr-package.mdstructures-types.mdwindows.md
tile.json

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.

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
mavenpkg:maven/net.java.dev.jna/jna@4.5.x

To install, run

npx @tessl/cli install tessl/maven-net-java-dev-jna--jna@4.5.0

index.mddocs/

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.