JObfuscator — Obfuscation for Java Source Code

Obfuscate your Java source code & algorithms to protect it against reverse engineering analysis, cracking and decompilation. JObfuscator has been used 54873 times so far!

Java source code

Obfuscated Java code

Global obfuscation options. When disabled will discard any @Obfuscate annotation.

System.out.println("1");
System.out.println("2");
System.out.println("3");
int JOWCN_FGIWJIGTWJ_JSDAO = 0;
JOWCN_FGIWJIGTWJ_JSDAO = 1148643996;
while (JOWCN_FGIWJIGTWJ_JSDAO != 1421874931) {
  switch(JOWCN_FGIWJIGTWJ_JSDAO) {
    case 797943348:
      System.out.println("3");
      JOWCN_FGIWJIGTWJ_JSDAO += 623931583;
      break;
    case 1148643996:
      System.out.println("1");
      JOWCN_FGIWJIGTWJ_JSDAO -= 911757835;
      break;
    case 236886161:
      System.out.println("2");
      JOWCN_FGIWJIGTWJ_JSDAO -= -561057187;
      break;
}

Read about code execution flow.

int myNum = 5;
float myFloatNum = 5.99f;
char myLetter = 'D';
boolean myBool = true;
String myText = "Java Obfuscator";
int ap9axcpArl_nyapT__QpnQOl_ = 5;
float var_3897 = 5.99f;
char aAqktfgaaaqRjhiouqlSwoqgob = 'D';
boolean nVdbxytrOhipcleakh = true;
String MUQJO_OGIEHC = "Java Obfuscator";

All references to the renamed variables are automatically fixed.

public int calc(double numArray[]) {...}
public int SqcFsxe(double[] numArray) {...}

All references are automatically fixed. main() entrypoint name remains intact. Methods annotated with @Override keyword are not renamed.

public static int methodNum1(int param)
{...}

public static int methodNum2(int param)
{...}

public static int methodNum3(int param)
{...}
public static int methodNum2(int param)
{...}

public static int methodNum3(int param)
{...}

public static int methodNum1(int param)
{...}

The order of Java methods in a source file is not important.

int[] ports = { 21, 80, 443 };
System.out.println(ports[0]);
int[] ports = { 43668, 43701, 43874 };
for (int i = 0; i < ports.length; i++) {
  ports[i] ^= 0xAAAA;
}
System.out.println(ports[0]);

Integer array contents are stored in encrypted form and decoded at runtime before use.

double[] scale = { 1.5, 2.75 };
return scale[1];
long[] data = { 4609434218613702656L, 4613374868287651840L };
double[] scale = new double[data.length];
for (int i = 0; i < data.length; i++) {
  scale[i] = Double.longBitsToDouble(data[i] ^ 0x55AA55AA55AA55AAL);
}
return scale[1];

Double array constants are hidden as encoded bit patterns and reconstructed while the program runs.

char[] token = { 'A', 'P', 'I' };
return token[2];
char[] token = { 0x1A, 0x0B, 0x12 };
for (int i = 0; i < token.length; i++) {
  token[i] = (char) (token[i] ^ 0x5B);
}
return token[2];

Character array literals are replaced with encrypted values and restored only through generated decoder code.

String[] roles = { "admin", "guest" };
return roles[0];
String[] roles = { "\u4708\u470d\u4704\u4700\u4707",
                   "\u470e\u471c\u470c\u471a\u471b" };

for (int j = 0; j < roles.length; j++) {
  char[] var_8 = roles[j].toCharArray();
  for (int var_8i = 0; var_8i < var_8.length; var_8i++) {
    var_8[var_8i] = (char) ((var_8[var_8i] ^ 18257) & 0xFFFF);
  }
  roles[j] = new String(var_8);
}
return roles[0];

String array elements are encrypted independently and rebuilt on demand by generated runtime code.

public static int method(int param) {
  int a = 1;
  int b = a + 2;
  int c = 0;
  if (b > 3) return c;

  return 4;
}
public static int method(int param) {
  int a = (int) (681.57415 - Math.cbrt(315229127.95597));
  int b = a + (int) (2.76739 - Math.acos(0.71973));
  int c = (int) (-1.20690 + Math.tan(0.87887));
  if (b > (int) (-1.85887 + Math.log10(72255.55488)))
    return c;
  return (int) Math.min(6525.74776, 4.00000);
}

Over 15 floating point math functions used from the java.lang.Math.* class.

System.out.println("Hello, World!");
System.out.println("Hel".concat("lo, World!");

Eligible literals are split into segments and rebuilt with nested String.concat calls, adding intermediate expressions for tools to analyze before polymorphic string encryption.

System.out.println("Java Obfuscator Online");
String var_127 = "";
int[] var_1774 = { 0xFB5F, 0xF9EF, 0xF89F, 0xF9EF,
                   0xFDFF, 0xFB0F, 0xF9DF, 0xF99F,
                   0xF8AF, 0xF8CF, 0xF9CF, 0xF9EF,
                   0xF8BF, 0xF90F, 0xF8DF, 0xFDFF,
                   0xFB0F, 0xF91F, 0xF93F, 0xF96F,
                   0xF91F, 0xF9AF };
for (int hGrz = 0, x = 0; hGrz < 22; hGrz++) {
  x = var_1774[hGrz];
  x ^= 0xFFFF;
  x = ((x << 12) | ((x & 0xFFFF) >> 4)) & 0xFFFF;
  var_127 += (char) (x & 0xFFFF);
}

System.out.println(var_127);

The polymorphic string encryption engine is taken from our StringEncrypt solution.

public static int method(int param) {
  int a = 1;
  int b = a + 2;
  int c = 0;
  if (b > 3) return c;

  return 4;
}
public static int method(int param) {
  int[] IFNMDK = { 0, 3, 2, 4, 1 };
  int a = IFNMDK[4];
  int b = a + IFNMDK[2];
  int c = IFNMDK[0];
  if (b > IFNMDK[1])
    return c;
  return IFNMDK[3];
}

It makes the analysis harder because it requires an indexed table lookup for every numeric value. As an extra obfuscation, the generated arrays are randomly declared as double arrays e.g. double[] IFNMDK = { 0.49128, 3.33891, 2.00013, 4.32255, 1.99981 };

public static double method(double param) {
  double a = 1.1;
  double b = a + 2.2;
  double c = 0.0;
  if (b > 3.3) return c;

  return 4.4;
}
public static double method(double param) {
  double[] xnn_dji_34 = { 0.0, 3.3, 2.2, 4.4, 1.1 };
  double a = xnn_dji_34[4];
  double b = a + xnn_dji_34[2];
  double c = xnn_dji_34[0];
  if (b > xnn_dji_34[1])
    return c;
  return xnn_dji_34[3];
}

It makes the analysis harder because it requires an indexed table lookup for every numeric value.

double price = 19.95;
double tax = price * 0.23;
double price = Math.min(19.95000, 824.22341);
double tax = price * (20.53912 - Math.sin(0.58974));

This rewrites floating point literals into equivalent expressions based on Math.* calls, so constants are no longer visible as plain numeric values.

String name = "Admin";
System.out.println(name);
String name = new String(new char[] {
  'A', 'd', 'm', 'i', 'n'
});
System.out.println(name);

This simple string vault converts literals into runtime-created String objects built from character arrays.

int retries = 7;
int zero = 0;
int retries = (int)(Math.sqrt(49.0));
int zero = (int)(Math.sin(0.0));

Integer literals are expressed through casts from equivalent double calculations such as square roots or trigonometric functions.

int sum(int a, int b) {
  return a + b;
}
static long QxRf7mz(long acc, int s) {
  long u = acc + (long) ((s & 0x7fff) + 1);
  return u ^ (long) Long.numberOfLeadingZeros((s | 1));
}

static long pBk2NwV(long acc, int s) {
  long h = Long.rotateLeft(acc ^ (long) Integer.reverse(s), (s & 63));
  return Long.reverseBytes(h) ^ (long) (s << 1);
}

int sum(int a, int b) {
  long v = QxRf7mz(0L, -402184);
  v = pBk2NwV(v, 881022);
  v = QxRf7mz(v, -15023);
  if (Long.compare(v, -8372144055286123915L) == 0) {
    int hxP9 = 0; }
  return a + b;
}

The obfuscator adds static mixer methods, invokes chains of them inside methods and emits guards that should never execute, increasing the amount of code a decompiler has to analyze.

boolean enabled = true;
boolean locked = false;
boolean enabled = (Integer.signum(8471) > 0);
boolean locked = (Character.isDigit('x'));

Plain true and false literals are replaced with equivalent comparisons or method calls that keep the same boolean result.

value += 10;
return value;
try {
  value += 10;
} finally {
  Integer.toHexString(1392).length();
}
return value;

Selected safe statements are wrapped in try/finally blocks with harmless no-op code in the finally section, adding control-flow noise while preserving behavior.


Want a free activation code?

Here are the ways that can get you a free activation code with 500 usage credits

Pencil

Write a post

Write a blog post or an article about JObfuscator with some screenshots, code examples and a link to the product site.

X

Post about it

Post on X about JObfuscator with a link to the product page — use the following hashtags #jobfuscator #java #obfuscator & #obfuscation.

Pencil

Report a bug

Report a bug and if I can confirm it you will get a free activation code as a thank you.

Idea

Suggest an obfuscation idea

If you have an idea for improving the current obfuscation methods, or a new technique, please contact me with some code samples.

Use the contact form to talk to me.

Questions?

If you would like to ask me about JObfuscator, or something's not clear, mail me. I'll be happy to answer all of your questions.