Java Bindings
The Java bindings are distributed as a JAR targeting Java 8. Native libraries for multiple platforms are embedded in the JAR's resources
directory. The
correct native library will automatically load during static initialization. These native libraries wrap the underlying C API with a thin layer of
JNI.
Shared libraries for the following platforms are included in the release JAR:
- Windows x64 (Windows 7+)
- Windows x86 (Windows 7+)
- Linux x64 (kernel 2.6.32+, glibc 2.11+)
- Linux AArch64 (kernel 4.2, glibc 2.17+)
- MacOS x64 (MacOS 10.7+, Lion+)
MacOS x64 libraries are included in the package but are not officially supported. They are useful for developers using MacOS, but are not supported in production.
It is also possible to use an external library by specifying its path in the DNP3_NATIVE_LIB_LOCATION
environment variable. This feature can be useful if your platform
is not officially supported and you built the bindings manually.
Maven
Release artifacts are published to Maven central. Add this dependency to incorporate them into your projects:
<dependency>
<groupId>io.stepfunc</groupId>
<artifactId>dnp3</artifactId>
<version>${dnp3.version}</version>
</dependency>
Dependencies
In addition to the Rust dependencies, the Java bindings depend on one open source project:
- joou-java-6 - Apache 2.0 - Java Object Oriented Unsigned (JOOU) integer classes
This library is not distributed by Step Function I/O directly. It is only declared as a dependency for the package manager to retrieve.
Unsigned Integers
Java doesn't support unsigned integers as part of the core language. Instead, the Java code generator uses classes from the JOOU
library. This ensures that numeric types crossing the Java/JNI boundary are pre-validated within the correct range. User code that creates unsigned integers will need to import symbols from the JOOU
library.
It is particularly helpful to statically import the factory methods on Unsigned
class:
import static org.joou.Unsigned.*;
import org.joou.UShort;
This lets you create instances of the unsigned classes:
UShort value = ushort(65535);
Mapping
Java is an object-oriented language that supports all the abstract patterns modeled in the code generator. This section describes those mappings.
Errors
C API errors are transformed into exceptions containing the error enum. The exception class inherits from RuntimeException
.
Uncaught exceptions thrown in callbacks will terminate the program. Always wrap your callback logic using try/catch
syntax if there's a possibility the callback will throw.
Iterators
Iterators are transformed into List<T>
by the code generator. This means that the collections returned by callbacks may be
used outside the callback. For example, you can send them to another thread for processing.
Structs
Native structs are mapped to Java classes. They have public member visibility, and the constructor ensures that all values without a reasonable default are initialized.
Each field has a with<FieldName>
method that sets the field and returns the struct for chaining operations.
Classes
Abstract classes are also mapped to Java classes. They have a private pointer to the underlying native resource. There are two types of generated classes in Java:
- Generated classes that only have a
finalize
method: These are automatically garbage collected, while native resources are deallocated in the class's finalize method. These types of classes are typically builder objects such asCommands
,Request
, andAddressFilter
. - Generated classes that also provide a public
Shutdown
method to proactively release native resources: These represent long-lived resources such asRuntime
,Master
, orTCPServer
. They map to an asynchronous Rust task executing on the Tokio runtime. TheShutdown
method lets you precisely control when the resource/task will stop.
Asynchronous Methods
Abstract asynchronous methods are transformed into methods that return CompletionStage<T>
. You can then chain and use the object in an asynchronous
workflow, or transform it into a CompletableFuture<T>
and call get()
.