Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to strip android.Log.d?

General assumptions

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()));

My Code

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 * ; }

Decompiled dex file

.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

Problem

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?

Further investigations

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.
like image 447
Giszmo Avatar asked Nov 12 '22 18:11

Giszmo


1 Answers

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)

like image 87
JesusFreke Avatar answered Dec 14 '22 14:12

JesusFreke