Every eligible class is renamed into one shared, flat package using short, opaque names
(a.a, a.b, ... rolling over past 26 the way a spreadsheet column
does). The rename is applied with a constant-pool-aware bytecode remapper, not hand-rolled
patching, so it rewrites every place a class name can appear: descriptors,
signatures, InnerClasses/EnclosingMethod metadata, annotation
values, an LDC of a Class literal, and stack-map frame type
entries.
Before any renaming happens, every LDC string operand and every
static final String field value across the whole JAR is collected. A
class whose name appears anywhere in that set, a Class.forName target, a
ServiceLoader provider-file entry, is excluded from renaming entirely, since a
bytecode remapper cannot see, and therefore cannot safely rewrite, a reference that only
exists as a string. The JAR's own Main-Class, if declared, is excluded, since renaming it would make the JAR unlaunchable. Interfaces are renamed like any other class
(nativization's separate, unrelated exclusion of interface methods doesn't apply
here, see Nativization).
A plain-text rename map (<output>.rename-map.txt, sorted, dotted form)
is written alongside the output JAR. RJNI does not read it back; it is there so you can tell
which obfuscated class was which when comparing before/after output.
Removes your package and class names from the constant pool and every metadata location a decompiler or a static analysis tool would otherwise read them from. Does not rename anything reachable only through a string constant, see Scope above, and a class with an external supertype still keeps its original name if renaming would otherwise break something this pass can't see (this specific case doesn't apply to class renaming itself, but does apply to member renaming, see Method & field renaming).
IllegalAccessError/VerifyError in
the output, including a package-private interface renamed consistently alongside its
public implementor, an edge case found and fixed during that run.