Decompilation SATest

Program-Transformation.Org: The Program Transformation Wiki

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