2012-10-31 15 views
5

Các giả định chung

Vì vậy, tôi đã tìm thấy rất nhiều về cách sử dụng trình bảo vệ để tách các câu lệnh nhật ký khỏi mã. Về cơ bản tất cả các thuật ngữ -assumenosideeffects cùng với việc sử dụng cấu hình $ {sdk.dir} /tools/proguard/proguard-android-optimize.txt sẽ làm điều này. hiểu biết của tôi là để có được bytecode đó là tương đương với làm một sốCách xóa android.Log.d?

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

aka tôi cho rằng để có được những cuộc gọi đến doSomeExpensiveStuff() loại khỏi apk tôi:

android.util.Log.d("Hello","World"+(new Foo().doSomeExpensiveStuff())); 

Mã My

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 tập tin 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 

Vấn đề

Bây giờ nếu tôi triển khai này vào điện thoại của tôi, tôi không nhận được bất kỳ dữ liệu ghi nhận nhưng vẫn ngủ 5s (hoặc bất kỳ chậm trễ khác hoặc tai nạn từ mã mà shouldn' t làm phiền người dùng của tôi). Tôi đang làm gì sai?

nghiên cứu sâu hơn

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

ứng dụng cùng một vấn đề gặp sự cố khi tôi sử dụng gói ứng dụng bị can thiệp bởi lệnh 'ant release' – juned

+0

@juned câu hỏi này không có gì để làm với sự cố ứng dụng;) – JesusFreke

Trả lời

0

Trong khi tôi không biết câu trả lời, tôi tin rằng có final static boolean DEBUG = false sẽ dẫn đến if(D) { Log.d(...) } được hoàn toàn lột bởi trình biên dịch

+0

Cảm ơn bạn Alex đã trả lời nhanh. Thật không may này "trên không" là không mong muốn mặc dù nó là workaround chỉ ngoài xấu xí sed-kịch bản mà tôi có thể đi lên với bây giờ. (Ngoài ra tôi muốn hiểu, tại sao proguard quan tâm nếu tôi in một chuỗi không đổi hoặc bắt đầu một hộp ảo bên trong một cuộc gọi Log (,) khi nó được nói rõ ràng để xem xét nó không có bất kỳ tác dụng phụ.) – Giszmo

+0

Ah , Tôi nghĩ bạn chỉ muốn loại bỏ đầu ra logcat, xin lỗi –

1

Dường như Proguard vẫn coi việc tạo ra ví dụ Slooow mới để có/có tác dụng phụ. Ở cấp bytecode mà Proguard hoạt động, có bản chất là có sự khác biệt giữa:

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

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

Vì vậy Proguard thấy Log.d, và dải mà ra, nhưng nó không tước ra việc tạo ra ví dụ Sloooow mới, bởi vì nó chưa được thông báo rằng không có tác dụng phụ.

Tôi không thể nghĩ ra bất kỳ cách nào tốt để loại bỏ việc tạo ra Sloooow(), mà không nói với proguard rằng nó không có tác dụng phụ. (Tôi không biết nếu điều đó thậm chí có thể xảy ra đối với một nhà xây dựng)

+0

Âm thanh hợp lý.Tôi cần ngủ và hy vọng một câu trả lời đầy hứa hẹn hơn thực sự giải quyết vấn đề của tôi nhưng tôi cảm thấy có chút ít để thêm vào, cho câu hỏi proguard-centerric của tôi :) – Giszmo

+0

Đúng vậy. ProGuard không biết rằng hàm tạo và phương thức toString không có các tác dụng phụ. Nói rõ ràng ProGuard có thể có các hiệu ứng không mong muốn, vì nó (hiện tại) áp dụng cho tất cả các hiện thực toString(), ví dụ. Và các phương thức StringBuilder có các tác dụng phụ, mặc dù chúng chỉ là nội bộ. Giải pháp có thể có: nếu bạn có thể tạo phương thức ghi nhật ký riêng chứa tất cả mã phụ, bạn có thể chỉ định -assumenosideeffects trên đó. –