Choose and test java decompiler [closed]

2019-01-13 00:32发布

问题:

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{}?

回答1:

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, JD 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.

EDIT, 5 years later:

CFR, Procyon, and Fernflower lead the way in this space.



回答2:

Procyon has it's own comparison.



回答3:

I have been using http://java.decompiler.free.fr/ for a long time now and found it to be the best one. In particular I used it to decompile a third-party jar and I was able to modify the source code as well with it.

Its easy to use and the UI is also neat and clean.

Update: Java Decompiler is no longer available on http://java.decompiler.free.fr/. It has new link http://jd.benow.ca/ from where it can be downloaded.



回答4:

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).



回答5:

It looks like fernflower and JD Java Decompiler 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.



回答6:

http://www.reversed-java.com/fernflower/, see my comparison on github.com /vorburger/ScratchApplet



回答7:

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

About the -g(javac) 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.


回答8:

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.



回答9:

It's been a while since any feedback to this thread. However since I found it and took the input seriously I feel it important to give an update.

I have used Java Decompiler Free with good success. However, recently I accidentally deleted quite a bit of code of a production J2EE application. assumed JD Free would handle it, but it doesn't handle generics at all. Plus there was code where it handled variable initialization totally wrong. What I ended up with was a total mess.

There may not be anything out there that will to the job correctly. In my case it's just another lesson in backup, backup, backup. I need a de-compiler that handles generics properly in order to do a mass recovery. But some accuracy of handling variables would also help. It is too much to ask a tool to spit out the original code. But what I have seen so far will compile but will not function properly, generics aside. So I suppose it's going to be a long week before Christmas!!