Decompilation SATest
Program-Transformation.Org: The Program Transformation Wiki
Source Again Java Decompiler Tests
Ahpah kindly provided a copy of
Source Again
Professional version 1.10j (a commercial decompiler).
Earlier tests were based on the demonstration decompiler available at
this website.
Fibo
For source code see
DecompilerFiboTestSource. Decompiled output:
//
// SourceAgain (TM) Professional v1.10j (C) 2003 Ahpah Software Inc
//
import java.io.PrintStream;
class Fibo {
private static int fib(int int1)
{
if( int1 > 1 )
return fib( int1 - 1 ) + fib( int1 - 2 );
else
return int1;
}
public static void main(String[] String_1darray1)
throws Exception
{
int int2 = 0;
int int3;
try
{
int2 = Integer.parseInt( String_1darray1[0] );
}
catch( Exception Exception4 )
{
System.out.println( "Input error" );
System.exit( 1 );
}
int3 = fib( int2 );
System.out.println( "fibonacci(" + int2 + ") = " + int3 );
}
}
The output compiled correctly with no modifications.
Casting
For source code see
DecompilerCastingTestSource. Here is the output from Source Again:
//
// SourceAgain (TM) Professional v1.10j (C) 2003 Ahpah Software Inc
//
import java.io.PrintStream;
public class Casting {
public static void main(String[] String_1darray1)
{
char char2;
for( char2 = (char) 0; char2 < 128; char2 = (char) (char2 + 1) )
System.out.println( "ascii " + char2 + " character " + char2 );
}
}
This is pretty and compact, but the cast is missing. The non professional version
(as for example available on the web) gives variable names that are to my mind prettier
(e.g. "c" vs "char2"), but both versions are incorrect.
Inner classes
For source code, see
DecompilerInnerClassesTestSource. When decompiled with Source Again, the result is:
//
// SourceAgain (TM) Professional v1.10j (C) 2003 Ahpah Software Inc
//
import java.io.PrintStream;
public class Usa {
public class England {
public class Ireland {
public String name = "Dublin";
public void print_names()
{
System.out.println( name );
}
}
public String name = "London";
}
public String name = "Detroit";
}
The inner classes are reproduced perfectly.
This is an area where the professional version differs markedly from the non professional version;
in the latter, the inner classes are completely missing.
Deuces Wild
This is a 38K applet with two dimensional arrays of integers, some floating point code, and so on.
The output from this decompiler is very readable. However, there were a few compile errors, all
associated with defining the variable
i
more than once. In a few cases, this was moderately serious,
because it was not clear which version of
i
some references were referring to. When these
errors were corrected, the application compiled without warning or error. It displayed the initial screen
correctly, but the cards did not turn over, and none of the buttons appeared to do anything.
Sable Test Program
For source code, see
DecompilerSableTestSource. Here is the result for function
f
(as produced by Source Again):
//
// SourceAgain (TM) Professional v1.10j (C) 2003 Ahpah Software Inc
//
public class Main {
public static void f(short short1)
{
Object Object4;
boolean boolean5;
if( short1 > 10 )
{
Object Object3 = new Rectangle( short1, short1 );
boolean5 = ((Rectangle) Object3).isFat();
Object4 = Object3;
}
else
{
Object Object2 = new Circle( short1 );
boolean5 = ((Circle) Object2).isFat();
Object4 = Object2;
}
if( !boolean5 )
((Drawable) Object4).draw();
}
public static void main(String[] String_1darray1)
{
f( (short) 11 );
}
}
Source Again has ignored the class hierarchy;
obj
is of type
Object
.
It is correctly cast as needed; the program compiles without error.
Optimised bytecode
For source code, see
DecompilerOptimisedTestSource. This was the result from Source Again for the method
f
:
//
// SourceAgain (TM) Professional v1.10j (C) 2003 Ahpah
//
public class Main {
public static void f(short short1)
{
Object Object2;
boolean boolean3;
if( short1 > 10 )
{
Object2 = new Rectangle;
(Rectangle) Object2( short1, short1 );
boolean3 = ((Rectangle) Object2).isFat();
Object2 = Object2;
}
else
{
Object2 = new Circle;
(Circle) Object2( boolean3 );
boolean3 = ((Circle) Object2).isFat();
Object2 = Object2;
}
if( !boolean3 )
((Drawable) Object2).draw();
}
public static void main(String[] String_1darray1)
{
f( (short) 11 );
}
}
In addition, the call to
new
and the constructor for both the
Rectangle
and the
Circle
object are separated. Strangely, all decompilers except
Dava have had this problem. Also, the parameter to the constructor for
Circle
should be
short1
, not
boolean3
.
Simple control flow
For source code, see
DecompilerControlFlowTestSource. Source Again produces:
public int foo(int int1, int int2)
{
while( int1 < int2 )
int1 = int2++ / int1;
return int2;
}
This is certainly wrong, because there is no exception handling code, and a divide by zero error is clearly possible.
Exceptions
For source code, see
DecompilerExceptionTestSource. Here is Source Again's output:
public void foo()
{
System.out.println( "a" );
label_15:
{
try
{
System.out.println( "b" );
try
{
System.out.println( "c" );
break label_15;
}
catch( Exception Exception1 )
{
System.out.println( "e" );
}
}
catch( RuntimeException RuntimeException2 )
{
System.out.println( "g" );
}
System.out.println( "f" );
return;
}
System.out.println( "d" );
}
While this is close to correct, block
d
is not protected (if an Exception occurs in block
d
, the code in
e
is supposed to be executed).
Life
When given the
URL for the Game of Life compiled from Ada 95 (from
http://www.appletmagic.com/download/demo/LifeRect.html), the demo decompiler produced output without fuss. Only classes
LifeRect
and
LR_Colony
were decompiled. There were a few problems, e.g.
tobj = new LR_Colony;
(LR_Colony) tobj();
should be
tobj = new LR_Colony();
Again, it was not possible to test much further because of the limitations of the demo decompiler.
CategoryDecompilation