Source Again Java Decompiler Tests
I have tried out
Source Again version 1.10i (a commercial decompiler) on the demonstration decompiler available at
this website. There is a limit of something like 300 lines of generated source code, so some of the tests are incomplete.
Fibo
For source code see
DecompilerFiboTestSource. Decompiled output:
//
// SourceAgain (TM) v1.10i (C) 2001 Ahpah Software Inc
//
import java.io.PrintStream;
class Fibo {
private static int fib(int i)
{
if( i > 1 )
return fib( i - 1 ) + fib( i - 2 );
else
return i;
}
public static void main(String[] as)
throws Exception
{
int i = 0;
int j = 0;
try
{
i = Integer.parseInt( as[0] );
}
catch( Exception exception1 )
{
System.out.println( "Input error" );
System.exit( 1 );
}
j = fib( i );
System.out.println( "fibonacci(" + i + ") = " + j );
}
}
The output compiled correctly with no modifications.
Casting
For source code see
DecompilerCastingTestSource. Here is the output from Source Again:
//
// SourceAgain (TM) v1.10i (C) 2001 Ahpah Software Inc
//
import java.io.PrintStream;
public class Casting {
public static void main(String[] as)
{
char c = 0;
for( c = (char) 0; c < 128; c = (char) (c + 1) )
System.out.println( "ascii " + c + " character " + c );
}
}
This is pretty and compact, but the cast is missing.
Inner classes
For source code, see
DecompilerInnerClassesTestSource. When decompiled with Source Again, the result is:
//
// SourceAgain (TM) v1.10i (C) 2001 Ahpah Software Inc
//
public class Usa {
public String name = "Detroit";
}
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 320 or so lines that come from the demo decompiler are only about 15% of the total output, so it is not possible to recompile the output. It is possible however to say that it produced readable code, and did not have the same problems with the two dimensional array
indeck
that
JReversePro had.
Sable Test Program
For source code, see
DecompilerSableTestSource. Here is the result for function
f
(as produced by Source Again):
//
// SourceAgain (TM) v1.10i (C) 2001 Ahpah Software Inc
//
public class Main {
Warning #2008: Inheritance relationship can not be determined because
Circle can not be found.
Warning #2008: Inheritance relationship can not be determined because
Rectangle can not be found.
Warning #2008: Inheritance relationship can not be determined because
Drawable can not be found.
public static void f(short si)
{
Object obj = null;
boolean bool = false;
if( si > 10 )
{
Object obj1 = new Rectangle( si, si );
bool = ((Rectangle) obj1).isFat();
obj = obj1;
}
else
{
Object obj2 = new Circle( si );
bool = ((Circle) obj2).isFat();
obj = obj2;
}
if( !bool )
((Drawable) obj).draw();
}
public static void main(String[] as)
{
f( (short) 11 );
}
}
This is possibly not a fair test, because the demo doesn't seem to have the ability to read other class files as needed (they were in the same directory as the decompiled class file). However, even without knowing the class hierarchy, Source Again has done the next best thing;
obj
is of type
Object
, and is correctly cast as needed.
Optimised bytecode
For source code, see
DecompilerOptimisedTestSource. This was the result from Source Again for the method
f
:
//
// SourceAgain (TM) v1.10i (C) 2001 Ahpah Software Inc
//
public class Main {
Warning #2008: Inheritance relationship can not be determined because
Circle can not be found.
Warning #2008: Inheritance relationship can not be determined because
Rectangle can not be found.
Warning #2008: Inheritance relationship can not be determined because
Drawable can not be found.
public static void f(short si)
{
Object obj = null;
boolean bool = false;
if( si > 10 )
{
obj = new Rectangle;
(Rectangle) obj( si, si );
bool = ((Rectangle) obj).isFat();
obj = obj;
}
else
{
obj = new Circle;
(Circle) obj( bool );
bool = ((Circle) obj).isFat();
obj = obj;
}
if( !bool )
((Drawable) obj).draw();
}
public static void main(String[] as)
{
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
si
, not
bool
.
Simple control flow
For source code, see
DecompilerControlFlowTestSource. Source Again produces:
public int foo(int i, int j)
{
while( i < j )
i = j++ / i;
return j;
}
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 runtimeexception1 )
{
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