Java binds through JNA, so there is no JNI layer for you to compile and no per-platform native build in your own project — the SDK ships the native libraries and JNA loads the right one.
Reading a license
try (Dongle dongle = Dongle.open()) { // first dongle found
if (!dongle.isGenuine()) throw new IllegalStateException("no genuine KeyNub");
dongle.sessionOpen();
byte[] license = dongle.recordRead("license");
}Code language: Java (java)
Dongle implements AutoCloseable, so try-with-resources closes the device on every path out of the block.
Why Java needs the data-gating pattern badly
Java bytecode decompiles almost perfectly. A licence check written as if (licensed) is visible in any decompiler and removable with a bytecode editor in minutes, and obfuscators only raise the effort. This is not a Java weakness so much as a reason not to rely on a branch at all.
And the rule that matters in every language: do not branch on a boolean. Encrypt data your program genuinely needs with appEncrypt at build time and decrypt it through the dongle at run time, so removing the check leaves the program with nothing to compute rather than a working unlicensed copy.