Current stage

RJNI is a solo, part-time project under active development. This page says what exists, what has been verified, and what has not. Last updated 21 September 2026.

Summary

The core pipeline works end to end: parse a JAR, translate eligible methods to Rust, compile them, relink through JNI, and repackage. Twelve protection passes are implemented. It has been run against a third-party JAR of about 1,200 classes. It has not yet shipped as a public build, and it is not feature-complete: a range of bytecode patterns are still excluded from translation, and only one operating system has been used for verification so far.

  • 63commits since 30 Aug 2026
  • ~29,000lines of Java and Rust
  • 12protection passes
  • 99.5%of methods nativized on a 1,208-class JAR
  • 2,415JVM tests passing, last full run
  • 124Rust tests passing
  • 2,282real classes parsed and round-tripped
  • 0class-loading errors on that 1,208-class JAR

Verified against real code

On 2 September 2026 the full protection pipeline was run on an unmodified third-party Fabric/Mixin Minecraft mod JAR with Kotlin interop, unrelated to any test project. All 1,208 classes were eligible and renamed. 3,303 of 3,321 methods were translated to native code, and the remaining 18 were rejected with categorised reasons. The output JAR produced no IllegalAccessError, VerifyError or ClassFormatError. The run also exposed four bugs, which were fixed.

Other checks: the class-file parser is fuzzed with Jazzer and may only fail with its documented malformed-class exception; translated methods are compared against the original Java behaviour on real open-source code; and continuous integration builds and lints both the Rust and Java sides.

What works today

Translation to Rust

Arithmetic and stack operations, branches and loops, method calls of every kind, lambdas and method references, objects, arrays and casts, long, float and double, exceptions and try/catch, whole-method synchronized, switches, bitwise and shift operators, string concatenation, static fields, and char, byte and short conversions.

Protection passes

Class and member renaming, string and constant encryption, control-flow flattening, decompiler-resistant wrapping, anti-tamper checksums, loader hardening, resource encryption, JDWP anti-debug detection, build-time watermarking, Kotlin metadata stripping, keep rules, and a deterministic trial mode.

Native loading

One native library per platform packaged inside the JAR under an obfuscated name, loaded by absolute path and bound with RegisterNatives.

Desktop app

A first-cut GUI wrapping the same protection entry point as the command line. Very early, and not yet at feature parity with the command line.

What does not work yet

Every entry below is rejected at protection time with a reason. None of them produces wrong output without warning. A method that hits one is left as ordinary bytecode.

JDK 8 to 16 at runtime

RJNI reads class files from JDK 8 through JDK 26. However, the runtime classes bundled into every protected JAR require JDK 17 or newer, so a protected application currently fails to load on older JVMs. Lowering that floor to JDK 8 is planned and not done.

Platforms

Development and verification began on macOS. A Windows toolchain was brought up this month. Linux builds have not been produced or tested, and cross-platform packaging is not yet validated in continuous integration.

Bytecode gaps

Multi-dimensional array literals, block-level synchronized, reference equality branches, some stack-duplication instructions, constructor references, nested try/catch, invokedynamic other than lambdas and string concatenation, and class-literal constants. Interface methods can never be native.

Packaging and tooling

RJNI runs as a JVM application against an input and output JAR. A packaged command-line tool and Gradle and Maven plugins are planned. Multi-release JAR handling and Windows cleanup of the extracted native library are also not done.

Other obfuscators

Because RJNI works on a finished JAR it can be run after another obfuscator, but output from ProGuard, ZKM, Allatori or DashO has not been systematically verified.

Performance

Native calls cost more than a JIT-compiled Java call. On a JMH benchmark of the worst case, a trivial getter, the original Java method took about 4.9 ns per call and the relinked native method about 293 ns, roughly 60 times slower. The gap comes from the fixed cost of crossing into native code, so it shrinks as a method does more work per call. RJNI is a protection tool, not a performance tool. Apply it to logic worth protecting, not to hot inner loops.

Timeline

  1. 30 Aug 2026

    Foundations

    Repository, competitor research, test corpus, class-file parser validated on 2,282 classes, first method translated end to end.

  2. 31 Aug 2026

    Translator and JNI relinking

    Control flow, calls, lambdas, objects and arrays, exceptions, and class-file relinking through RegisterNatives. Continuous integration added.

  3. 1 Sep 2026

    Whole-JAR protection

    Switched from single methods to whole-JAR nativization. Class renaming, string encryption, trial mode, anti-tamper, decompiler-resistant wrapping and control-flow flattening.

  4. 2 Sep 2026

    Real-world hardening

    Ran against the 1,208-class JAR and fixed the bugs it exposed. Added obfuscated native bundling, keep rules, resource encryption, anti-debug, watermarking, member renaming, loader hardening and a benchmark suite.

  5. 6 to 7 Sep 2026

    Self-audit and fixes

    A sceptical review against established commercial obfuscators found correctness bugs. All confirmed ones were fixed with end-to-end regression tests. Switch, bitwise, shift and string-concatenation support added, and the JDK 17 runtime floor was found and fixed.

  6. 21 Sep 2026

    Windows and array access

    Windows development machine brought online and the native toolchain fixed. Byte and boolean array element access closed.

What is next

  • Close the remaining bytecode gaps by running more real, uncurated JARs through the tool.
  • Lower the runtime floor from JDK 17 towards JDK 8.
  • Build and verify on Linux and Windows, with CI for each target.
  • Repeat the sceptical self-audit. Licensing and activation are on hold until it comes back clean.
  • Publish original and protected sample JARs, then a packaged CLI and build-tool plugins.

Also see the security model and known limitations.