views:

1647

answers:

7

Now I'm trying to find the best java decompiler, I found these:

http://java.decompiler.free.fr/

http://www.reversed-java.com/fernflower/

http://dj.navexpress.com/

http://cavaj-java-decompiler.en.softonic.com/

With these decompilers I handle byte code of this class:

public class ss
{
public static void main(String args[])
{
  try{
   System.out.println("try");

  }
  catch(Exception e)
  {
   System.out.println("catch");
  }
  finally
  {System.out.println("finally");}
}
}

and I got the following results:

fernflower:

public class ss {

   public static void main(String[] var0) {
      try {
         System.out.println("try");
      } catch (Exception var5) {
         System.out.println("catch");
      } finally {
         System.out.println("finally");
      }

   }
}

DJ Java Decompiler:

import java.io.PrintStream;

public class ss
{

    public ss()
    {
    }

    public static void main(String args[])
    {
        System.out.println("try");
        System.out.println("finally");
        break MISSING_BLOCK_LABEL_50;
        Exception exception;
        exception;
        System.out.println("catch");
        System.out.println("finally");
        break MISSING_BLOCK_LABEL_50;
        Exception exception1;
        exception1;
        System.out.println("finally");
        throw exception1;
    }
}

cavaj:

import java.io.PrintStream;

public class ss
{

    public ss()
    {
    }

    public static void main(String args[])
    {
        System.out.println("try");
        System.out.println("finally");
        break MISSING_BLOCK_LABEL_50;
        Exception exception;
        exception;
        System.out.println("catch");
        System.out.println("finally");
        break MISSING_BLOCK_LABEL_50;
        Exception exception1;
        exception1;
        System.out.println("finally");
        throw exception1;
    }
}

http://java.decompiler.free.fr/:

import java.io.PrintStream;
public class ss
{
  public static void main(String[] paramArrayOfString)
  {
    try
    {
      System.out.println("try");
    }
    catch (Exception localException)
    {
      System.out.println("catch");
    }
    finally {
      System.out.println("finally");
    }
  }
}

I see that the best result in decompiler: http://java.decompiler.free.fr/

To test, I wrote very simple code. What do you think, what code to write to test decompilers? Maybe the idea is to better than a try{} catch(){} finally{}?

A: 

One of every statement, of course.

Interesting that you got such garbage ...

EJP
A: 

Ok, this is written from my mobile phone so bear with me.

1st of all, every java file codes are compiled in bytecode in their respective .class file. This means that constants are stored AS IS (hence strings can easily be retrieved) and variables are assigned to a register that is then put on a stack program execution when the JVM process the class file.

The reason your exception block are not returned to the original code you've written is because of the way javac compiled & translated the code to java bytecode.

If you want to know which decompiler works best, write all java well known statements (for loop, if statement, while loop) with some expressions & see what best represent your original code.

Good luck.

The Elite Gentleman
Local variables are assigned directly to a stack slot.
EJP
A: 

It looks like fernflower and http://java.decompiler.free.fr/ are producing decompiled code that is as good as is possible for this particular testcase. The other two aren't doing a good job, IMO.

What do you think, what code to write to test decompilers?

  1. Write more complicated code using all available constructs.
  2. Try them out on some real code.
  3. Try them out on some real code that has been obfuscated.

When trying out code that you compile from source, experiment with different "-g" options, and with different Java compilers.

Stephen C
A: 

Some time ago I've used JAD (http://en.wikipedia.org/wiki/JAD_%28JAva_Decompiler%29). I didn't make any comparisons so I don't know which decompiler is the best.

iirekm
+3  A: 

The code that you use to test should test the features available the in JDK used to compile the target class. For example, if you know that your target is written in Java 1.5, it is reasonable to assume that the code might include generics, so you will want to make sure that your chosen decompiler handles them properly. In my experience, the freely available decompilers tend to lag behind the JDK releases in terms of the features they support by 1-2 releases.

Based on personal trial and error, http://java.decompiler.free.fr/ tends to do the best job in general. However, if you're decompiling code that was written in 1.3 or lower, I'd also suggest you give JODE a try.

Segphault
+2  A: 

For information, JD supports switch(enum), switch(string), assert statements and for-each loops.

About the -g options,

  • if you omit the line numbers, JD can not reconstruct the original flow of instructions : the types of loop can not be determinate, the multiple assigments can not be regenerate, and the algorithm used to realign source code can not work.
  • if you omit the local variable data, JD can not, sometime, determine the exact range of variables. It's problematic.
Emmanuel Dupuy
A: 

If you anticipate to get any meaningful results, you really should test with a bit more non-trivial code. Fernflower was created with the aim of handling highly unusual and obfuscated bytecode. Thus decompiling such simple snippets is no big deal. By the way, if you are interested in testing the stand-alone version of Fernflower drop me a note at fernflower(dot)decompiler(at)gmail(dot)com. Version 0.8.4 is now in semi-public beta (however not available on the website yet).

Stiver