2012-10-31 78 views
5

一般假設

所以我發現很多關於使用proguard從代碼中去除日誌語句。基本上所有的說--assumenosideeffects與使用$ {sdk.dir} /tools/proguard/proguard-android-optimize.txt配置將做的伎倆。我的理解是讓字節等於做一些如何去掉android.Log.d?

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 

問題

現在,如果我部署此我的設備,我沒有得到任何日誌輸出,但仍是5秒睡眠(或其它任何延遲或崩潰的代碼,不該」不要打擾我的用戶)。 我在做什麼錯?

進一步調查

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. 
+0

遇到同樣的問題的應用程序崩潰時,我使用的是由'ant釋放命令混淆的apk – juned

+0

@juned這個問題沒有任何事情要做與應用程序崩潰;) – JesusFreke

回答

0

雖然我不知道答案,我相信,有final static boolean DEBUG = false將導致if(D) { Log.d(...) }由編譯器

+0

謝謝亞歷克斯的快速回復。不幸的是,這種「開銷」並不是我們所期望的,儘管它是除了醜陋的sed腳本之外唯一可以替代的解決方法。 (另外我想明白,爲什麼如果我打印一個常量字符串或在Log()調用中啓動一個虛擬框時明確告訴它認爲它沒有任何副作用,爲什麼proguard會關心它。) – Giszmo

+0

啊,我以爲你只是想剝離logcat輸出,對不起 –

1

它看起來像的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它沒有任何副作用。 (我不知道如果這是甚至可能爲一個構造函數)

+0

聽起來似乎合理。我需要一些睡眠和希望,以一個稍微更有希望的答案,實際上安全地解決了我的問題,但不知何故,我覺得有一點補充,鑑於我的proguard爲中心的問題:) – Giszmo

+0

這是正確的。 ProGuard不知道構造函數和toString方法沒有副作用。明確告訴ProGuard可能會產生不良影響,因爲它會(當前)適用於所有toString()實現。而StringBuilder方法確實有副作用,即使它們只是內部的。可能的解決方案:如果您可以創建包含所有額外代碼的自己的日誌記錄方法,則可以在其上指定-assumenosideeffects。 –