0

Are JAD decompiled files 100% accurate. I am decompiling some jar files to get the source code and when i am trying to build the project with these java files it is not showing the accurate build. Does i am doing it wrong or the decompiled files are not accurately same as the original one.

nikhilgupta86
  • 472
  • 3
  • 15
  • 1
    The source file could be obfuscated. Anyway try using jd-gui – Marco Acierno May 16 '14 at 14:30
  • no, there is no comments, local variable names (if you don't have debug), original line numbers, original compile time constants, original formatting etc. These are all because they are not in the byte code. – Peter Lawrey May 16 '14 at 15:04
  • 1
    Bytecode for while() {} and for() {} is not clearly distinguishable, the decompiler may replace one for the other (semantics stay the same). Some bytecode is impossible to decompile properly to java (e.g. generated code, code generated by other VM-based languages compilers). – Durandal May 16 '14 at 15:38
  • In addition compiler generates helper methods to make inner classes work ([see this](http://stackoverflow.com/a/663147/5128464)) – vlp Sep 19 '15 at 23:12

1 Answers1

4

Short answer: 99% of the time, decompiled code will not look like the original code, but it should behave the same way. So, assuming the decompiler doesn't make any mistakes, it should be accurate in function, but not in implementation.

Long answer: When the Java compiler translates your source to byte code, it performs certain operations that change how to code looks. I am not an expert on the details of the Java compiler, but A simple optimisation that many compilers perform is inserting small methods into the location in code where they are called.

For example, lets say we compile this code:

public class c
{
   public int add(int a, int b)
   {
      return a + b;
   }

   public static void main(String [] args)
   {
      int i = add(1, 2);
   }
}

Since b is only one line, and it can safely be substituted with it's contents, a smart compiler may change the main method into this:

public static void main(String [] args)
{
   int a = 1, b = 2
   int i = a + b;
}

or this:

public static void main(String [] args)
{
   int i = 1 + 2;
}

This would be done because the overhead for calling a method is worse than the overhead of putting the method's contents directly into the place it's called.

I have no idea what the Java compiler would do in this situation, but it does make changes to the code like this. It isn't necessarily inaccurate, because it does do the same thing as the original code. Since the compiler doesn't leave the details of these changes anywhere in the .class file, there is no way for a decompiler to know whether an optimisation was performed at any given point in the code, of if it was written that way.

There are also a number of other things that may not survive the transition to byte code (variable names and comments, for instance).

So yes, when you look at decompiled code, you are looking at what the .class file looks like, rather than what the .java file looks like. Even though it seems inaccurate, it should run the same.

RyNo
  • 203
  • 2
  • 4
  • 3
    The Java compiler itself will **not** perform inlining in the way that you described. It could *theoretically* do this if the method was `private`, but even then, it will not do such a change, because it has to preserve the structure of the class (for example, for the case that the method is accessed via reflection). Inlining is done by the JIT. – Marco13 May 16 '14 at 16:16
  • Yeah, I haven't studied the Java compiler closely, so I wasn't exactly sure what to use as an example. I decided on that one because it was easy to explain, and it gets the point across that changes are made to the structure of the code, even if it isn't as applicable to Java as it may be for other platforms. If someone who knows more about Java compilers has a better example, I would be happy to add it (or change my answer to a community wiki). – RyNo May 16 '14 at 16:36
  • 2
    The most common differences you'll see will be subtle changes in branching, e.g., you might see `while(a) { if (!b) f(); }` where the author had originally written `while(a) { if (b) continue; f(); }` or `a = b ? c : d` where the author had written `if (b) a = c; else a = d;`. You may see more intermediate variables introduced, and some values inlined. But you should **never** assume that the decompiled output is functionally equivalent to the original code. It is intended to be, but decompilers are not infallible. – Mike Strobel May 16 '14 at 19:51
  • @MikeStrobel I've changed my answer to a community wiki, as you guys have proven I don't know quite enough about Java compilers to write a good answer. Feel free to improve it. – RyNo May 16 '14 at 20:04