一般假设
所以我发现了很多关于使用proguard从代码中剥离日志语句的信息。基本上,所有人都会说 - insumenosefects,以及使用$ {sdk.dir}/tools/proguard/proguard/proguard-android-optimize.txt配置将可以解决问题。我的理解是获得等于做一些
的字节码if(Consts.DEBUG) Log.d("","");
又名我假设从我的apk中取出的dosomeExpensivestuff()呼叫:
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 * ; }
分解dex文件
.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
问题
现在,如果我将其部署到设备上,我没有获得任何日志输出,但仍然5s睡眠(或任何其他不应该打扰用户的代码的延迟或崩溃)。我在做什么错?
进一步研究
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.
看起来proguard仍然认为新的 Slooow
实例的创建是/具有副作用。在Proguard工作的字节码级别上,基本上没有以下区别:
Log.d("tag", "onCreate: " + (new Slooow().toString()));
和
String temp = new Sloooow().toString();
Log.d("tag", "onCreate: " + temp);
proguard看到了Log.d
,并将其剥离,但是它并没有剥离新的Sloooow
实例的创建,因为没有被告知没有副作用。
我想不出任何一个很好的方法来剥离Sloooow()的创建,而没有特别告诉Proguard它没有副作用。(我不知道构造函数是否可以使用)
虽然我不知道答案,但我相信拥有final static boolean DEBUG = false
会导致if(D) { Log.d(...) }
被编译器完全剥离