Protections
Native protection
Move methods out of Java into compiled native code.
Setting: native.enabled. This moves selected methods out of the JVM entirely — they get compiled to a small custom instruction set, turned into native code by the Zig compiler, and loaded back into your program over JNI. It's the strongest protection flowguard offers, and the most involved to set up.
Requirements
- A working Zig compiler on your
PATH(or pointnative.zigat it directly). - Mark the methods you want protected with
@pbco.nativeh.Native(see Annotations).
Keep native methods simple
A method marked @pbco.nativeh.Native must not contain branches (if/for/while/switch) or rely on local variables the way a normal method would. Breaking this rule can corrupt array arguments and crash at runtime with an "Invalid state" error. Keep these methods small and straightforward — simple calculations and data transforms, not full program logic.
Target platform
Setting: native.target. Choose the platform your protected jar will run on (Windows by default). The native library flowguard builds is specific to one platform, so if you ship to multiple platforms, run a separate build for each.
Reproducible builds
Setting: native.vmSeed. By default, every build generates slightly different native code, so output isn't identical between runs. Set a fixed value here (64 hex digits) if you need the exact same output every time — useful for comparing builds or verifying a release.
Hardening options
A further set of options under Advanced native settings tune how the native layer itself is protected — things like anti-debugging checks and integrity checks on the compiled library. These are good defaults left on; most projects won't need to change them. Two of them, anti-debug and integrity checking, aren't available on macOS.
Note
Native protection needs real setup and testing time. Start with everything else, get a protected build you trust, and add native protection once you're comfortable.