JODEPowered by SourceForge
Best viewed with Any

Using the Decompiler

After you have downloaded the jar archive put it into your CLASSPATH. The package swingall.jar is also needed if you are using JDK 1.1.

There is also a batch file for windows and a script file for unix, that you can use. You can extract it with the following command:
  jar -xvf jode-1.1-jdk1.1.jar bin/jode.bat resp. bin/jode
Edit the file to adapt it to your paths and put it to a convenient location.

Command Line Interface

The most powerful way to start JODE's decompiler is the command line interface. Some people don't like long command lines; they should go to the next section.
Start the class jode.decompiler.Main with the options. The following command will give a complete list of the available commands:
java jode.decompiler.Main --help
If you want to decompile a jar package you can do it this way:
java jode.decompiler.Main --dest srcdir program.jar
If you have installed the batch file/script, you can use it like this:
jode --dest srcdir program.jar

AWT Interface

The AWT Interface looks exactly like the applet. In fact the applet uses the AWT Interface. You start it after setting the CLASSPATH (see above), with
java jode.decompiler.Window
In the classpath line you can enter a number of jar files, zip files and directories separated by comma(,). Then enter the dot(.) separated name of the class you want to decompile. Press the start button and the decompiled class should appear. You can save it via the save button.

Swing Interface

For the swing interface you need java version 1.2 or the separately available swing package (see link page. You can invoke it with the following command:
java jode.swingui.Main classes.jar
resp. jode swi classes.jar

The swing interface will show the package hierarchie of all classes in the classpath on the left side. You can now select a class and the decompiled code will appear on the right side. Via the menu, you may change the classpath or switch between package hierarchie tree and class inheritence tree.

The swing interface is very useful to browse through class files if you don't have the source code. You can also use it to trace bugs in library code. It is not meant to generate java files and so you won't find a save option there.

Java Interface

If you want to integrate JODE into your own java program, you can use the jode.decompiler.Decompiler class. Note that the LGPL allows dynamic linking as long as you don't change Jode itself. Please tell me if you use JODE in this way.

You should ship jode-1.1-embedded.jar with your program. This jar file is available in the download area. It works only under JDK 1.2 and above.

Using the Obfuscator

To use the obfuscator you should first create a script file, say myproject.jos. Then you can invoke the obfuscator with:

java jode.obfuscator.Main myproject.jos

The script file should contain the following options:

First select the classpath. You should include everything in the classpath that you need to run your application. This also includes the system class files (Sun puts them into or rt.jar))

classpath = "c:\\jdk1.2\\jre\\lib\\rt.jar","d:\\project\\java",

Specify where you want the obfuscated classes to go. I recommend to write them directly into a zip file, but you can also give a directory.

dest = ""

You can make JODE write its translation table. This table can be used later to undo the name obfuscation, or you can look there to decrypt exceptions you may get.

revtable = "translat.tbl"

Select what you want to strip. There are several possibilities, which can be separated by comma(,):

strip unreachable methods and classes.
remove the name of the java file (exceptions will get unreadable).
remove the line number table (exceptions will get unreadable).
remove the local variable table (debugging doesn't work).
strip inner class info (reflection doesn't work correctly).
strip = "unreach","lvt","inner"

Select the packages and classes you want to obfuscate. You should only include libraries, that you don't ship separately. If you give a package, all classes and subpackages are loaded. You can also use * as wild card, that matches everything (including dots).

load = new WildCard { value = "org.myorg.myproject" },
       new WildCard { value = "org.myorg.mylib*" },
       new WildCard { value = "org.otherorg.shortlib" }

Select the methods and classes you want to preserve. This is the main method for applications and the default constructor <init>.()V for applets, resource bundles and other classes that you load manually at runtime.
You have to give the method name and the type signature to identify your method. javap -s will show you the type signatures for your classes, but you may also use *, to select all methods with that name. If you have serializable classes and want to preserve their serialized form you can use the SerializePreserver.

preserve = new SerializePreserver,
           new WildCard { value = "org.myorg.ApplicationClass.main.*" },
           new WildCard { value = "org.myorg.AppletClass.<init>.()V" },
           new WildCard { value = "org.resources.Bundle*.<init>.()V" },

If you want to obfuscate (or just shorten) the identifier you can specify a renamer. There are currently following renamer available

Renames to the shortest possible name. You can give a charset that should be used. It uses the same name as much as possible.
Renames to unique identifier of the form xxx123. Useful to reduce name conflicts, before you decompile an obfuscated package.
This renamer just swaps the names. This is a funny obfuscation option that is not very strong, but very confusing.
Renames identifiers to keyword. You can give your own list of keywords as parameters. Resulting code is not decompilable directly, but it is not legal bytecode either. Some paranoid web browsers refuse to run applets containing keywords as identifiers (and they are completely within the Java VM spec).
renamer = new StrongRenamer

You can also create a renaming table with the same format as the table written by revtable. The entries in the table get precedence over renamer. Entries not in the table will get renamed by the renamer.

table = "translat.tbl"

Now you can select the analyzer. The purpose of the analyzer is to mark all reachable methods, find out which methods needs to get the same name (overloading), and which method names mustn't change (overload of library methods, e.g. nextElement for Enumerations). There are currently two analyzers.

Straight forward analyzer. It is fast and will remove dead code on method basis.
Strong analyzer that will determine, which fields and instructions have constant values. It will remove dead code on instruction basis and replace constant instruction with a load of the constant, or remove them completely.
This analyzer is especially useful to revert the flow obfuscation of some other obfuscators.
analyzer = new ConstantAnalyzer

Pre- and Post transformers transform the bytecode before resp. after the Analyzer runs. Using this default should be okay. You may remove the LocalOptimizer, though, if you have problems.

In the future I may add some new post transformers, that do string encryption, flow obfuscation and similar things. If you want to write your own Transformers please contact me, since the next version will change the bytecode interface.

post = new LocalOptimizer, new RemovePopAnalyzer