So I found a lot about using proguard to strip log statements from code. Basically all say -assumenosideeffects together with using the ${sdk.dir}/tools/proguard/proguard-android-optimize.txt config would do the trick. My understanding was to get bytecode that is equal to doing some
if(Consts.DEBUG) Log.d("","");
aka I assumed to get the call to doSomeExpensiveStuff() eliminated from my apk:
android.util.Log.d("Hello","World"+(new Foo().doSomeExpensiveStuff()));
public class MainActivity extends Activity {
private class Slooow {
@Override
public String toString() {
// being slow
try {
Thread.sleep(5000);
} catch(InterruptedException e) {
}
return "bla";
}
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d("tag", "onCreate: " + (new Slooow().toString()));
}
}
proguard-project.txt:
-repackageclasses ''
-optimizationpasses 5
-dontobfuscate
-assumenosideeffects class android.util.Log { public * ; }
.method public onCreate(Landroid/os/Bundle;)V
.limit registers 5
; this: v3 (Lcom/example/test/MainActivity;)
; parameter[0] : v4 (Landroid/os/Bundle;)
.line 18
invoke-super {v3,v4},android/app/Activity/onCreate ; onCreate(Landroid/os/Bundle;)V
.line 19
const/high16 v0,32515
invoke-virtual {v3,v0},com/example/test/MainActivity/setContentView ; setContentView(I)V
.line 20
new-instance v0,java/lang/StringBuilder
const-string v1,"onCreate: "
invoke-direct {v0,v1},java/lang/StringBuilder/<init> ; <init>(Ljava/lang/String;)V
new-instance v1,com/example/test/MainActivity$Slooow
const/4 v2,0
invoke-direct {v1,v2},com/example/test/MainActivity$Slooow/<init> ; <init>(B)V
invoke-virtual {v1},com/example/test/MainActivity$Slooow/toString ; toString()Ljava/lang/String;
move-result-object v1
invoke-virtual {v0,v1},java/lang/StringBuilder/append ; append(Ljava/lang/String;)Ljava/lang/StringBuilder;
.line 21
return-void
.end method
Now if I deploy this to my device, I don't get any log output but still the 5s sleep (or any other delay or crash from code that shouldn't bother my users). What am I doing wrong?
Log.d("t", "h" + "w"); // would get stripped just fine.
if(DEBUG)
Log.d("t", "h: " + (new Slooow().toString())); // would get optimized away, too.
Log.d("t", "h" + bundle.toString()); // has just the same problem as described above.
It looks like proguard still considers the creation of the new Slooow
instance to be/have a side effect. At the bytecode level at which proguard works, there is essentially no difference between:
Log.d("tag", "onCreate: " + (new Slooow().toString()));
and
String temp = new Sloooow().toString();
Log.d("tag", "onCreate: " + temp);
So proguard sees the Log.d
, and strips that out, but it's not stripping out the creation of the new Sloooow
instance, because it hasn't been told that that has no side effects.
I can't think of any good way to generically strip out the creation of Sloooow(), without specifically telling proguard that it has no side effect. (I don't know offhand if that is even possible for a constructor)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With