Java SDK 概述
xyz.darra:darra-ai 是对 darra_ai.h 的 JNI 薄封装:只翻译类型和错误码,不另造语义,零密码学。权威契约 = Core/include/darra_ai.h;hint 文案与 错误码目录 逐字一致。版本 1.0.0(AiRuntime.VERSION_MAJOR/MINOR/PATCH,与头文件 DARRA_VERSION_* 对齐)。
主 jar 纯 Java,不内嵌 dll/so。native(DarraAI.Core + darraai_jni)按 classifier 另打。
包名 xyz.darra.ai。方法 camelCase(openPlain / inferImage / ensureCancel)。错误是 AiException 的嵌套子类:AiException.IoNotFoundException。会话实现 AutoCloseable,用 try-with-resources。
安装
- Maven
- Gradle
- 手动引用 JAR
<dependency>
<groupId>xyz.darra</groupId>
<artifactId>darra-ai</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>xyz.darra</groupId>
<artifactId>darra-ai</artifactId>
<version>1.0.0</version>
<classifier>natives-windows-x86_64</classifier>
</dependency>
Linux x64 把 classifier 换成 natives-linux-x86_64;Linux ARM64 / RK3588 用 natives-linux-aarch64。authoring 风味(仅 AI Studio)为 natives-<os>-<arch>-authoring。
implementation 'xyz.darra:darra-ai:1.0.0'
implementation 'xyz.darra:darra-ai:1.0.0:natives-windows-x86_64'
不走 Maven/Gradle 时:
- 从 下载页面 取主 jar 与对应平台 natives
- 主 jar 加入 classpath
- natives 用系统属性
xyz.darra.ai.natives.dir指向目录,或放进java.library.path
包坐标与仓内既有 Java SDK 一致:groupId=xyz.darra(EtherCAT darra-ethercat-master、OPC UA darra-opcua-sdk、PnS darra-pns-slave)。artifactId=darra-ai。JDK 17(maven.compiler.release 17)。
环境要求
- 操作系统 — Windows x64、Linux x86_64、Linux aarch64(RK3588)。macOS / 32 位 / 其它架构由
NativeLoader抛AiException.UnsupportedPlatformException - Java — JDK 17
- native — 运行时需要
DarraAI.Core.dll+darraai_jni.dll(Linux 为libdarraai_core.so+libdarraai_jni.so)。缺库时加载失败,不放假二进制 - Windows 上指名
edge-rknn— Core 返回UNSUPPORTED_PLATFORM(RKNN 只在 linux-arm64)
加载后核 ABI:darra_version() 的 major 必须等于 NativeLoader.HEADER_MAJOR(1),否则拒绝继续。
快速开始
明文 ONNX(Studio 试跑 / 客户自有未加密模型):
import xyz.darra.ai.*;
AiRuntime.ensure("cpu-only", null, (percent, stage) ->
System.out.printf("[%s] %.1f%%%n", stage, percent));
try (AiSession session = AiSession.openPlain("model.onnx", "onnx-cpu")) {
String meta = session.metaJson();
byte[] jpg = java.nio.file.Files.readAllBytes(java.nio.file.Path.of("a.jpg"));
String json = session.inferImage(jpg, ImageDesc.auto());
}
openPlain 的第二参是 preferProvider;null = 按载荷 × 硬件 × 已装包自动选。训练格式(.pt / .pth / Paddle)抛 AiException.UnsupportedPayloadException。
加密容器
key 与 password 至少给一个;都给则 key 文件优先验票。preferProvider 指名但不可用 = fail-closed,不静默降级。
try (AiSession s = AiSession.open("model.darmodel", "model.darmkey", null, null)) {
String json = s.inferImage(pixels, ImageDesc.rgb888(640, 480));
}
也可走可扩展入口(当前翻译到 open;Core 落地 darra_session_open_ex 后只换调用点):
SessionOptions opt = SessionOptions.empty()
.keyPath("model.darmkey")
.preferProvider(null);
try (AiSession s = AiSession.openEx("model.darmodel", opt)) {
String json = s.inferImage(jpg, ImageDesc.encoded());
}
工业相机裸缓冲
裸缓冲禁止 ImageDesc.auto()(嗅探不出通道序)。stride = 0 表示紧凑(= width × 3)。
byte[] frame = grabBgrFrame(); // 调用方自己的采集
String results = session.inferImage(
frame, ImageDesc.bgr888(1920, 1080, 0));
诊断与取消
诊断可能触发 WMI / NVML / sysfs,耗时可到数百毫秒,禁止放进 PLC 扫描周期。推理不承诺硬实时。
String diag = AiDiagnostics.collect();
取消在飞的 ensure:任意线程可调(含 UI 线程);进度回调内禁止再调任何本 SDK 方法(含 ensureCancel)。没有在飞的 ensure 时为 no-op。失败/取消不留半成品。
AiRuntime.ensureCancel();
进度回调在 SDK 工作线程触发:percent 0..100,stage ∈ probe / manifest / download / verify / install / done。只准记录或转发到自己的 UI 队列。
类一览
| 类型 | 作用 |
|---|---|
AiRuntime | ensure / ensureCancel / packedVersion / versionString。对应 darra_runtime_ensure / darra_version |
AiSession | 推理会话(AutoCloseable):open / openPlain / openEx / metaJson / inferImage / close |
ImageDesc | auto / encoded / rgb888 / bgr888。对应 darra_image_desc |
PixelFormat | AUTO(0) / ENCODED(1) / RGB888(2) / BGR888(3),与 darra_image_format 逐值对齐 |
SessionOptions | keyPath / password / preferProvider;构造不加载 native |
AiDiagnostics | collect() — 环境自检 JSON(去敏,不含密钥/密码/token/机器指纹字节) |
AiException | 每个 darra_error_code(除 OK)一个嵌套子类 |
NativeLoader | 加载 JNI + Core;runtimeClassifier() / authoringClassifier() |
xyz.darra.ai.authoring.Authoring | 仅 authoring natives:encryptOnnx / issueKey / fingerprintPerturb |
AiSession 从 meta JSON 抽出的只读字段:task() / labels() / inputWidth() / inputHeight() / channels() / layout() / payloadKind() / providerId() / encrypted()。缺席时字符串为 null、标签为空列表、宽高通道为 0。
不同会话可并发;同一会话 inferImage 允许多线程并发(吞吐扩展仍推荐每线程一个会话)。close() 禁止与任何在飞调用并发;关闭后句柄失效。NULL/重复 close 安全。
Provider / profile ID
AiRuntime.ensure 合法 ID(源码注释):
- 细包:
onnx-cpu/onnx-cuda/onnx-openvino/onnx-trt-ep/trt-native/edge-rknn(仅 linux-arm64) - 场景整合包:
cpu-only/nvidia-gpu/intel-iap/amd-dml/board-rk3588 null= 按硬件探测自动选细包
ensure 幂等;进程内串行。offlineZip 为离线整合包 zip 路径;null = 在线下载。
natives classifier
| classifier | 内容 | 使用场景 |
|---|---|---|
natives-windows-x86_64 | DarraAI.Core.dll + darraai_jni.dll | Windows x64 runtime |
natives-linux-x86_64 | libdarraai_core.so + libdarraai_jni.so | Linux x64 runtime |
natives-linux-aarch64 | 同上 so | Linux ARM64 / RK3588 runtime |
natives-<os>-<arch>-authoring | authoring 风味 Core + JNI(定义 DARRA_AUTHORING) | 仅 AI Studio |
classifier jar 内资源路径(NativeLoader 从 classpath 抽出):
natives/windows-x86_64/DarraAI.Core.dll
natives/windows-x86_64/darraai_jni.dll
natives/linux-x86_64/libdarraai_core.so
natives/linux-x86_64/libdarraai_jni.so
natives/linux-aarch64/libdarraai_core.so
natives/linux-aarch64/libdarraai_jni.so
加载顺序(NativeLoader):
- 系统属性
xyz.darra.ai.natives.dir指向的目录 - classpath 上
natives/<os>-<arch>/ java.library.path/System.loadLibrary("darraai_jni")(Core 先试DarraAI.Core,再试darraai_core)
错误处理
失败时 JNI 调 darra_last_error,再 AiException.throwByCode。hint 原文透传,不改写。getCode() / getMessage() / getHint() 分别对应 C 的 code / message / hint。未知码抛基类,不丢信息。code == 0 为 no-op。
try {
// Open / InferImage
} catch (AiException ex) {
System.err.println(ex.getMessage()); // C 的 message
System.err.println(ex.getHint()); // error-catalog 给最终用户的修复建议
}
| 码 | C 常量 | Java 异常 |
|---|---|---|
| 1 | DARRA_IO_NOT_FOUND | AiException.IoNotFoundException |
| 2 | DARRA_IO_DENIED | AiException.IoDeniedException |
| 3 | DARRA_BAD_CONTAINER | AiException.BadContainerException |
| 4 | DARRA_BAD_LICENSE | AiException.BadLicenseException |
| 5 | DARRA_PASSWORD_REQUIRED | AiException.PasswordRequiredException |
| 6 | DARRA_PASSWORD_WRONG | AiException.PasswordWrongException |
| 7 | DARRA_MACHINE_MISMATCH | AiException.MachineMismatchException |
| 8 | DARRA_TRIAL_EXHAUSTED | AiException.TrialExhaustedException |
| 9 | DARRA_UNSUPPORTED_PAYLOAD | AiException.UnsupportedPayloadException |
| 10 | DARRA_UNSUPPORTED_PLATFORM | AiException.UnsupportedPlatformException |
| 11 | DARRA_PROVIDER_MISSING | AiException.ProviderMissingException |
| 12 | DARRA_PROVIDER_ABI_MISMATCH | AiException.ProviderAbiMismatchException |
| 13 | DARRA_HARDWARE_MISSING | AiException.HardwareMissingException |
| 14 | DARRA_DRIVER_TOO_OLD | AiException.DriverTooOldException |
| 15 | DARRA_NETWORK_FAILED | AiException.NetworkFailedException |
| 16 | DARRA_CHECKSUM_MISMATCH | AiException.ChecksumMismatchException |
| 17 | DARRA_CANCELLED | AiException.CancelledException |
| 18 | DARRA_INTERNAL | AiException.InternalException |
参数契约违反(空路径 / 空 imageBytes / 空 desc / 裸缓冲宽高 ≤ 0 / 会话已关闭)归 InternalException。逐码含义见 错误码目录。
authoring
xyz.darra.ai.authoring.Authoring 只在 authoring natives 上真正转发 darra_encrypt_onnx / darra_issue_key / darra_fingerprint_perturb。runtime JNI 未定义 DARRA_AUTHORING,调用抛 InternalException:「当前为 runtime 构建,authoring API 物理上不存在(仅 AI Studio 安装包导出)」。Java 侧仍然零密码学。
请使用 NativeLoader.authoringClassifier() 对应的 natives 包。调用顺序:扰动 → 加密 → 签发。
import xyz.darra.ai.authoring.Authoring;
Authoring.fingerprintPerturb("model.onnx", "model.perturbed.onnx", customerSeed);
Authoring.encryptOnnx("model.perturbed.onnx", "model.darmodel");
Authoring.issueKey("model.darmodel", password, "model.darmkey"); // 默认不绑机、永久授权
// 绑机 / 试用计次:issueKey(container, password, outKey, bindMachine, trialRuns)
issueKey 的 trialRuns:0 = 永久授权;>0 = 试用计次。password 为 null = 本授权不启用密码。
编译 JNI 桥
仓库路径 Darra.AI.Studio.SDK/Java/darra-ai/src/main/cpp/jni_bridge.c。Windows(JDK include + Core 头):
cl /W4 /utf-8 /c ^
/I "%JAVA_HOME%\include" /I "%JAVA_HOME%\include\win32" ^
/I ..\..\..\Core\include ^
jni_bridge.c
链接时再链 DarraAI.Core.lib,产出 darraai_jni.dll。Linux:
cc -Wall -Wextra -fPIC -c \
-I "${JAVA_HOME}/include" -I "${JAVA_HOME}/include/linux" \
-I ../../../Core/include \
jni_bridge.c
authoring 风味加 -DDARRA_AUTHORING。