6

When building and deploying an executable on Android without running ProGuard, are unreferenced methods included in the final executable?

Are unreferenced methods from external library jars included as well?

Is this behavior dependent upon the Java compiler, or does dex do all the trimming, if any?

Jeff Axelrod
  • 27,676
  • 31
  • 147
  • 246
  • Not an exact dupe, but see this for lots of very useful information: http://stackoverflow.com/questions/4912695/what-optimizations-can-i-expect-from-dalvik-and-the-android-toolchain – Graham Borland Jun 29 '12 at 14:07
  • @GrahamBorland Thanks, I took a look and couldn't find any information in the question or answer about whether or not unreferenced code is included. – Jeff Axelrod Jun 29 '12 at 14:10

1 Answers1

5

I tested with a simple class (all these methods are unreferenced) :

public class Test
{
    private void privateMethod()
    {
        System.out.println("private");
    }

    protected void protectedMethod()
    {
        System.out.println("protected");
    }

    public void publicMethod()
    {
        System.out.println("public");
    }

    void method()
    {
        System.out.println("method");
    }
}

I compiled the APK, extracted Test.class and decompiled it (with javap -c). I got the following results. I also tested with a jar instead of an APK, and the result is exactly the same. I used Java 1.6.0_29.

  protected void protectedMethod();
    Code:
       0: getstatic     #44             // Field java/lang/System.out:Ljava/io/PrintStream;
       3: ldc           #47             // String protected
       5: invokevirtual #46             // Method java/io/PrintStream.println:(Ljava/lang/String;)V
       8: return        

  public void publicMethod();
    Code:
       0: getstatic     #44             // Field java/lang/System.out:Ljava/io/PrintStream;
       3: ldc           #48             // String public
       5: invokevirtual #46             // Method java/io/PrintStream.println:(Ljava/lang/String;)V
       8: return        

  void method();
    Code:
       0: getstatic     #44             // Field java/lang/System.out:Ljava/io/PrintStream;
       3: ldc           #49             // String method
       5: invokevirtual #46             // Method java/io/PrintStream.println:(Ljava/lang/String;)V
       8: return        

Which means only private functions are excluded at compile time.

I also tried to declare the class final, but the result was the same.

Jeff Axelrod
  • 27,676
  • 31
  • 147
  • 246
Dalmas
  • 26,409
  • 9
  • 67
  • 80
  • 2
    This may also depend on the actual compiler used. Furthermore we are on Android therefore the dexification step may also optimize the code. – Robert Jun 29 '12 at 15:08
  • @Robert how could Dalmas have compiled to an apk and avoid dexing? – Jeff Axelrod Jun 29 '12 at 16:06
  • 1
    Yes, I extracted the class from classes.dex in the APK (with dex2jar). However, I don't know if this optimization comes from the Java compiler or from the dexification. – Dalmas Jun 29 '12 at 16:17
  • 1
    Dalmas, if you wouldn't mind documenting which Java version you used, I'd appreciate it. Someone could then use the same version of the compiler to generate a jar file rather than an Android executable to determine if its the compiler doing the trimming. – Jeff Axelrod Jun 29 '12 at 19:21
  • 1
    I just tested with a jar instead of an APK, and the result is exactly the same. I used Java 1.6.0_29. – Dalmas Jun 30 '12 at 09:11