Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android Proguard does not inline

I am using the latest Android SDK (4.1) and I tried exporting a signed jar with Proguard enabled. However, after decompiling the optimized APK, I noticed that methods that I would have expected to be inlined were not.

I know that Proguard ran because the code was correctly obfuscated. So to confirm this, I added this method to my Activity:

private void testInlining()
{
    mConfig = null;
}

This private method is called only once in my activity, and because it is private, it should be very obvious to the optimizer that it is called only once and that it should be inlined.

The documentation says that all optimizations are enabled by default, and that Proguard "Inline methods that are short or only called once".

Is there a specific flag I should give to Proguard to enable inlining?

EDIT

My proguard configuration file contains

-optimizationpasses 5
-allowaccessmodification
-overloadaggressively
-repackageclasses ''
-dontskipnonpubliclibraryclasses

EDIT

After using

-whyareyoukeeping class com.templatecompany.templateappname.EntryPointActivity {*;}

I get the reason why the method is not inlined:

 [proguard] com.templatecompany.templateappname.EntryPointActivity: void testInlining() (20:21)
 [proguard]   is invoked by    com.templatecompany.templateappname.EntryPointActivity: com.td.media.ivConnection.IvConfig getIvConfig() (14:15)
 [proguard]   implements       com.td.widget.MainActivity: com.td.media.ivConnection.IvConfig getIvConfig()
 [proguard]   is invoked by    com.td.widget.MainActivity: void onCreate(android.os.Bundle) (140:175)
 [proguard]   implements       android.app.Activity: void onCreate(android.os.Bundle)
 [proguard]   is a library method.

But I am not sure to see how the fact that the method testInlining is used in the method getIvConfig which is in turn used by another method prevents the inlining on testInlining in getIvConfig.

like image 387
J_D Avatar asked Aug 24 '12 15:08

J_D


2 Answers

This recent Android SDK disables all optimizations by default, see ${sdk.dir}/tools/proguard/proguard-android.txt:

-dontoptimize

The alternative optimizing configuration only disables a few optimizations, see ${sdk.dir}/tools/proguard/proguard-android-optimize.txt:

-optimizations !code/simplification/arithmetic,!code/simplification/cast,!field/*,!class/merging/*

You can specify your preferred configuration file in project.properties.

You can verify which complete configuration ProGuard is using by adding the option -printconfiguration.

Some optimizations have been disabled in order to avoid bugs in older versions of the Dalvik VM (!code/simplification/arithmetic,!code/simplification/cast), and some optimizations may have been disabled to avoid bugs in older versions of ProGuard (!field/*,!class/merging/*).

Note that -whyareyoukeeping refers to the shrinking step, which removes unnecessary classes/fields/methods as a whole. Methods that are not removed may be inlined in the optimization step (unless explicitly specified otherwise with -keep).

like image 129
Eric Lafortune Avatar answered Nov 20 '22 19:11

Eric Lafortune


In your module's build.gradle file, you should look at:

buildTypes {
    release {
        minifyEnabled true
        shrinkResources true
        proguardFiles getDefaultProguardFile('proguard-android.txt'), file('proguard-project.txt')
        signingConfig signingConfigs.release
    }
}

and replace proguard-android.txt with proguard-android-optimize.txt, which doesn't include the -dontoptimize line while keeping the dalvik problems away (see Eric Lafortune's answer).

like image 36
Louis CAD Avatar answered Nov 20 '22 20:11

Louis CAD