I use Proguard 6.0.1 by enforcement within Android Studio 2.3 due to another error (similar to https://sourceforge.net/p/proguard/bugs/682/ ). I enforce this version in my top-level build.gradle:
buildscript {
configurations.all {
resolutionStrategy {
force 'net.sf.proguard:proguard-gradle:6.0.1'
}
}
...
dependencies {
classpath 'com.android.tools.build:gradle:2.3.0'
classpath 'me.tatarka:gradle-retrolambda:3.6.1'
}
...
The most important proguard options I use:
# retrolambda:
-dontwarn java.lang.invoke.*
-dontwarn **$$Lambda$*
# /retrolambda
-flattenpackagehierarchy
-dontshrink # todo temporary - Takes very long
#-optimizations "code/removal/*,code/simplification/*" # No error with this, but ignores -assumenosideeffects
-keep class android.*
-keep class java.*
-keep class sun.*
-keepnames class android.support.multidex.* {
*;
}
# Update of proguard-android file:
-keepclassmembers,allowoptimization enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
-assumenosideeffects class my.project.* {
static void f();
void f();
}
-assumenosideeffects class my.project.util.Utils {
public static Object noSideEffects(...);
}
-assumenosideeffects public interface my.project.util.function.NoSideEffectsSupplier { *; }
-assumenosideeffects class my.project.util.logging.SLogger {
public void f(...);
public void fs(...);
}
-assumenosideeffects class android.util.Log {
public static int v(...);
public static int d(...);
}
-assumenosideeffects class java.io.PrintStream {
public void println(%);
public void println(**);
}
From the apps build.gradle:
android {
...
// retrolambda
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
// / retrolambda
buildTypes {
release {
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
lintOptions {
disable 'MissingTranslation'
}
}
}
}
dependencies {
compile 'com.android.support:multidex:1.0.1'
...
}
apply plugin: 'me.tatarka.retrolambda'
I manually install the signed release build on a device, but on app launch I get this error:
I/art: Verification error in void android.support.multidex.MultiDex.<init>()
I/art: void android.support.multidex.MultiDex.<init>() failed to verify: void android.support.multidex.MultiDex.<init>(): [0x0] Constructor returning without calling superclass constructor
E/art: Verification failed on class android.support.multidex.MultiDex in /data/app/my.project.android.myapp-1/base.apk because: Verifier rejected class android.support.multidex.MultiDex due to bad method void android.support.multidex.MultiDex.<init>()
D/AndroidRuntime: Shutting down VM
--------- beginning of crash
E/AndroidRuntime: FATAL EXCEPTION: main
Process: my.project.android.myapp, PID: 11014
java.lang.VerifyError: Verifier rejected class android.support.multidex.MultiDex due to bad method void android.support.multidex.MultiDex.<init>() (declaration of 'android.support.multidex.MultiDex' appears in /data/app/my.project.android.myapp-1/base.apk)
at my.project.android.myapp.MyApp.attachBaseContext(Unknown Source)
at android.app.Application.attach(Application.java:181)
at android.app.Instrumentation.newApplication(Instrumentation.java:996)
at android.app.Instrumentation.newApplication(Instrumentation.java:980)
at android.app.LoadedApk.makeApplication(LoadedApk.java:564)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4634)
at android.app.ActivityThread.access$1500(ActivityThread.java:156)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1412)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:211)
at android.app.ActivityThread.main(ActivityThread.java:5389)
at java.lang.reflect.Method.invoke(Native Method)
...
I get the same error when omitting the following rule:
-keepnames class android.support.multidex.* {
*;
}
I get no error when uncommenting this line:
-optimizations "code/removal/*,code/simplification/*"
But then, -assumenosideeffects will be ignored. I dont want to miss any optimizations.
The problem is the loading of the MultiDex class which is a library by Android (which does not use Retrolambda), but somehow ProGuard seems to corrcupt it. Probably v6 is responsible for this.
With limited optimizations, the bytecode viewer shows the MultiDex private constructor as
and with full optimizations:
The problem is caused by
The wildcard also matches the constructor, which spills over to the constructor of Object. ProGuard then removes all calls to Object.<init>, which breaks other code. ProGuard probably already prints out a warning about the setting; you should generally avoid wildcards in
-assumenosideeffects. You should also be very careful about removingprintlncalls, since some code may really require them.</init>Thanks for this information! Now it works.
I still need to solve the following problem: I'd like to have a certain API to run commands as explicitly without side-effects, like this:
My rules to remove such calls currently are:
But the call will not be removed, probably because the init rule for subclasses is not sufficient. How can I accomplish the complete removement of
Utils.noSideEffects()without getting errors?Last edit: Andreas 2018-07-23