I compiled some [relatively complex] Java code into a .class file, then used jad to decompile it back into java. Of course, the code was obfuscated, which was to be expected. However, given that I had the original code, I thought I'd be able to look through the decompiled code fairly easily. However, I noticed differences in the code, such as where certain variables were defined (including differences of scope).
Is there any main reason for this? I imagine it's one of those things that just happen in decompilation of code, but I'm more curious about what factors cause the change (e.g. complexity of code, whether it refers to other files, etc.).
Could someone provide me with a good explanation on what factors cause the differences in the code before and after?
Edit
Technically, the .class file is pulled from a jar. I extracted the contents and used the .class file in there.
As far as which obfuscator I used, I used the Retroguard obfuscator with the following options (I'm currently just exploring obfuscation and finding out what each thing does to the final result):
.option Application
.option Applet
.option Repackage
.option Annotations
.option MapClassString
.attribute LineNumberTable
.attribute EnclosingMethod
.attribute Deprecated
Documentation for the script can be found on their site. It's a little unorganized, but you should be able to find adequate explanations in there. It's also noteworthy that I stripped the generics and the local variable table.
I have now also set up a way (inspired by the creators of the Minecraft Coder Pack) to rename the sources using data from a file (or files), which is passed to a dictionary of lists for packages, classes, methods, and fields.
# snippet from the MCP version (mine's slightly different) (all in Python):
srg_types = {'PK:': ['obf_name', 'deobf_name'],
'CL:': ['obf_name', 'deobf_name'],
'FD:': ['obf_name', 'deobf_name'],
'MD:': ['obf_name', 'obf_desc', 'deobf_name', 'deobf_desc']}
parsed_dict = {'PK': [],
'CL': [],
'FD': [],
'MD': []}
A line is then parsed from the file, and it is passed into the parsed_dict
and then used to rename everything (back and forth). Implemented after compiling than decompiling the first time (after I noticd differences).