Reads class files from JDK 8 through JDK 26 (major versions 52 to 70). Protected output currently needs JDK 17 or newer at runtime.
Input: major versions 52 through 70, covering every JDK LTS release from JDK 8 through the current JDK 26, parsed with ASM. Verified against a six-project open-source corpus spanning the in-scope LTS releases, and against an unmodified third-party JAR of about 1,200 classes.
The runtime classes RJNI bundles into every protected JAR are currently compiled for
JDK 17. A protected application therefore needs JDK 17 or newer at runtime, even if the
original JAR targeted an older release. Lowering this floor towards JDK 8 is planned and
not yet done; it requires rewriting the bundled runtime without records and
HexFormat, and reworking closure dispatch for older JVMs.
Lambda and method-reference call sites resolved via LambdaMetafactory are
supported, and string concatenation compiled through StringConcatFactory is
desugared and translated. Constructor references and other invokedynamic
bootstrap methods are not yet supported; a method using one is excluded with a
reason, not mistranslated.
try/catch, a throw, whole-method
synchronized, and generics all translate correctly with no dedicated work.
Generics are erased at the bytecode level RJNI operates on, and whole-method
synchronized is carried by the method's own access flag, not by
bytecode instructions, so it's transparent to relinking. Records and sealed classes work
through their standard bytecode desugaring, with no separate handling.
Not yet translated, and excluded, not mistranslated: multi-dimensional
array literals, a synchronized(obj) { ... } block (as distinct from a
whole-method modifier), object reference-equality branches (==/!=
on two references, and == null checks), nested try/catch
blocks, some stack-duplication instructions, and class-literal constants. Categorised
list:
Known limitations.