2012-10-31 7 views
5

Presupposti generali

Quindi ho trovato molto sull'utilizzo di proguard per rimuovere le istruzioni di registro dal codice. Fondamentalmente tutti gli effetti di tipo -assumenoside insieme all'utilizzo della configurazione $ {sdk.dir} /tools/proguard/proguard-android-optimize.txt farebbero il trucco. La mia comprensione era quello di ottenere bytecode che è uguale a fare un po 'Come spogliare android.Log.d?

if(Consts.DEBUG) Log.d("",""); 

aka ho assunto per ottenere la chiamata a doSomeExpensiveStuff() eliminato dal mio 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 * ; } 

file di dex decompilato

.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 

Problema

Ora, se schiero questo al mio dispositivo, non ottengo alcun output di registro, ma ancora il sonno 5s (o qualsiasi altro ritardo o incidente dal codice che shouldn' t infastidire i miei utenti). Cosa sto sbagliando?

Ulteriori indagini

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

si è verificato un arresto anomalo dell'applicazione stessa quando ho utilizzato l'apk che è offuscato dal comando 'ant release' – juned

+0

@ juned questa domanda non ha nulla da fare con un crash dell'applicazione;) – JesusFreke

risposta

0

Mentre io non conosco la risposta, credo che avere final static boolean DEBUG = false si tradurrà in if(D) { Log.d(...) } essere completamente spogliato dal compilatore

+0

Grazie Alex per la rapida risposta. Sfortunatamente questo "overhead" non è desiderato, anche se è l'unica soluzione alternativa al brutto sed-scripting che potrei inventare per ora. (Anche io voglio capire, perché proguard si preoccupa del tutto se stampo una stringa costante o avvio una casella virtuale all'interno di una chiamata Log (,) quando viene esplicitamente detto di non considerare alcun effetto collaterale.) – Giszmo

+0

Ah , Ho pensato che volevi semplicemente togliere l'output del logcat, scusate –

1

Sembra Proguard considera la creazione di ancora la nuova istanza Slooow deve avere/avere un effetto collaterale. A livello bytecode in cui funziona Proguard, non v'è nessuna differenza sostanziale tra:

Log.d("tag", "onCreate: " + (new Slooow().toString())); 

e

String temp = new Sloooow().toString(); 
Log.d("tag", "onCreate: " + temp); 

Così Proguard vede la Log.d e strisce che fuori, ma non è Escludendo la creazione di la nuova istanza Sloooow, perché non è stato detto che non ha effetti collaterali.

Non riesco a pensare a un buon modo per spogliare genericamente la creazione di Sloooow(), senza specificatamente dire a Proguard che non ha alcun effetto collaterale. (Non so se è possibile anche per un costruttore)

+0

suoni plausibili.Ho bisogno di dormire e sperare in una risposta un po 'più promettente che risolva in modo sicuro il mio problema, ma in qualche modo mi sembra che ci sia poco da aggiungere, data la mia domanda proguard incentrata :) – Giszmo

+0

Questo è corretto. ProGuard non sa che il costruttore e il metodo toString non hanno effetti collaterali. Dire esplicitamente che ProGuard potrebbe avere effetti indesiderati, dato che si applicherebbe (attualmente) a tutte le implementazioni di toString(), per esempio. E i metodi StringBuilder hanno effetti collaterali, anche se sono solo interni. Soluzione possibile: se è possibile creare il proprio metodo di registrazione che contiene tutto il codice aggiuntivo, è possibile specificare gli effetti -assumenoside su di esso. –