
St3ix Obfuscator
A Java bytecode obfuscator that transforms JAR files to make reverse engineering harder. Class names, strings, numbers, and more—all while preserving runtime behavior.
Quick Start
# Build the obfuscator
./gradlew dist
# Obfuscate a JAR
java -jar build/dist/st3ix-obfuscator-v*.jar -i myapp.jar -o myapp-obfuscated.jar
# Open GUI (Linux, macOS, or if you want to keep it simple)
java -jar build/dist/st3ix-obfuscator-v*.jar
Requirements: Java 17+, Gradle (wrapper included). Windows: use gradlew.bat and run.bat or java -jar for the GUI.
Before & After
Decompiled view: readable source becomes unreadable after obfuscation. Class names, methods, fields, numbers, strings, and control flow are transformed.
Flow obfuscation, numbers & strings▼
Before (original source)
package example;
public final class ObfuscationVerifyDemo {
private static final String apiKey = "verify-field-renaming";
public static void main(String[] args) {
ObfuscationVerifyDemo demo = new ObfuscationVerifyDemo();
demo.verify();
}
public void verify() {
int port = 25565;
int seed = 12345;
int threshold = 1000;
int sum = port + seed + threshold;
System.out.println("ObfuscationVerifyDemo: port=" + port + ", seed=" + seed + ", threshold=" + threshold);
System.out.println("Sum=" + sum);
System.out.println("Field (apiKey): " + apiKey);
}
}After (decompiled output)
import java.nio.charset.StandardCharsets;
public final class i\u202ffpdnbunzqoaxx {
private static final String rokb\u200c\u0435eg\u0441\u0445ldl;
public static void main(String[] stringArray) {
int n = 999980078;
block5: while (true) {
switch (n ^ 0x3B9A7C2E) {
case 0: {
i\u202ffpdnbunzqoaxx i2 = new i\u202ffpdnbunzqoaxx();
n = 999980079;
continue block5;
}
case 1: {
i2.\u043euxl\u200bbvwtg\u043f\u0430wnk();
n = 999980076;
continue block5;
}
case 2: return;
}
}
}
public void \u043euxl\u200bbvwtg\u043f\u0430wnk() {
int n = (6391 << 2) + (0x811D228E ^ 0x811D228F);
int n2 = (6172 << (0x811D228E ^ 0x811D228F)) + (0x811D228E ^ 0x811D228F);
int n3 = 637 + 363;
System.out.println("ObfuscationVerifyDemo: port=" + n + ", seed=" + n2 + ", threshold=" + n3);
byte[] byArray = new byte[]{192, 238, 237, ...};
int n5 = i\u202ffpdnbunzqoaxx.class.getName().hashCode() ^ 0xD30F1B4C;
for (int i = 0; i < byArray.length; ++i) {
byArray2[i] = (byte)(byArray[i] ^ n5 + i & 0xFF);
}
System.out.println(new String(byArray2, StandardCharsets.UTF_8));
}
static {
byte[] byArray = new byte[]{240, 226, 250, ...};
rokb\u200c\u0435eg\u0441\u0445ldl = new String(byArray2, StandardCharsets.UTF_8);
}
}Flow obfuscation (switch/case), number obfuscation (25565→expr, 12345→expr, 1000→expr), string XOR, homoglyph/invisible chars.
Cross-class references▼
Before (original source)
package example;
import example.model.User;
import example.util.StringHelper;
public final class CrossRefTest {
private final DemoService service;
private final User user;
public CrossRefTest() {
this.service = new DemoService();
this.user = new User("test-user", 42);
}
public void run() {
service.run();
String reversed = StringHelper.reverse("cross-ref");
System.out.println("Reversed: " + reversed);
String formatted = StringHelper.formatIdLinear(user.getId());
System.out.println("Formatted: " + formatted);
System.out.println("User: " + user);
}
}After (decompiled output)
import java.nio.charset.StandardCharsets;
public final class qm\u200c\u0443rjzo\u0441ub\u0441ijf {
private final nb\u200dxmhknidyfjnv \u200ad\u043ermtgvh\u0441\u0445zz = new nb\u200dxmhknidyfjnv();
private final yaghdirkvtrn\u0443g\u200d \u2060vk\u0445hoqoubjm\u0445;
public qm\u200c\u0443rjzo\u0441ub\u0441ijf() {
byte[] byArray = new byte[]{106, 122, 83, 85, 15, 86, 87, 64, 84};
int n = qm\u200c\u0443rjzo\u0441ub\u0441ijf.class.getName().hashCode() ^ 0xD30F1B4C;
byte[] byArray2 = new byte[byArray.length];
for (int i = 0; i < byArray.length; ++i) {
byArray2[i] = (byte)(byArray[i] ^ n + i & 0xFF);
}
this.\u2060vk\u0445hoqoubjm\u0445 = new yaghdirkvtrn\u0443g\u200d(new String(byArray2, StandardCharsets.UTF_8), 123 - 81);
}
public void \u0441qvfujvngavlad\u200b() {
this.\u200ad\u043ermtgvh\u0441\u0445zz.m\u0435s\u0435h\u200ebbh\u0441c\u0441gcj();
byte[] byArray = new byte[]{125, 109, 79, 82, 81, 14, 86, 64, 64};
String string = ag\u0430kdkeuorhfzr\u200a.ignxmtpme\u200bsgp\u0430b(new String(byArray2, StandardCharsets.UTF_8));
System.out.println("Reversed: " + string);
String string2 = ag\u0430kdkeuorhfzr\u200a.\u043f\u043fiulqyhzitrf\u200bh(this.\u2060vk\u0445hoqoubjm\u0445.sdibe\u200blvrnochxt());
System.out.println("Formatted: " + string2);
System.out.println("User: " + String.valueOf(this.\u2060vk\u0445hoqoubjm\u0445));
}
}Class renaming (CrossRefTest→qm..., DemoService→nb..., User→yag...), method renaming (run→...), string obfuscation, homoglyphs in identifiers.
Features
| Status | Feature | Description |
|---|---|---|
| ✓ | Class renaming | Short or random names, configurable length |
| ✓ | Method renaming | Handles override chains; excludes main, constructors, native |
| ✓ | Field renaming | Excludes serialVersionUID and enum constants |
| ✓ | Homoglyph & invisible chars | Unicode lookalikes and zero-width chars in names |
| ✓ | Number obfuscation | int via math expressions; long/float/double via XOR |
| ✓ | Array obfuscation | Hides array dimensions (XOR) |
| ✓ | Boolean obfuscation | Hides true/false literals (XOR) |
| ✓ | String obfuscation | XOR encryption; inline decrypt; static final fields in <clinit> |
| ✓ | Debug info stripping | Removes source names, line numbers, local vars |
| ✓ | GUI | Graphical interface (java -jar or run.bat) |
| ✓ | YAML config | config.yml next to the JAR |
| ✓ | Flow obfuscation | Control flow transformations |
| ○ | Mapping file output | Planned |
✓ = Implemented ○ = Planned
Actively Developed
St3ix Obfuscator is under active development. New features are added regularly, and existing behavior is refined based on real-world use. Contributions, feedback, and feature requests are welcome via Discord or GitHub issues.
FAQ
Which Java version is required?▼
Java 17 or later. The obfuscator and your input JARs must run on a compatible JVM.
Is it similar to ProGuard?▼
St3ix focuses on obfuscation (renaming, flow, strings, numbers). ProGuard also shrinks and optimizes code. Use St3ix when you want strong obfuscation without tree-shaking.
Does it work with Bukkit / Minecraft plugins?▼
Yes. Use excludeClasses in config.yml to exclude Bukkit, Spigot, or other framework packages. See the documentation for patterns.
Can I use it from the command line or CI/CD?▼
Yes. Use java -jar st3ix-obfuscator.jar -i input.jar -o output.jar. Perfect for Gradle tasks, GitHub Actions, or other build pipelines.
Ready to protect your Java applications?
Read the Documentation