1. 程式人生 > >JAVA之程式碼混淆proguard基礎(一)

JAVA之程式碼混淆proguard基礎(一)

講解的比較全面的一篇文章http://blog.csdn.net/glony/article/details/8852245

一官方網站用法

              http://proguard.sourceforge.net/index.html#/manual/examples.html

   基礎:

Input/Output Options
Keep Options
Shrinking Options
Optimization Options
Obfuscation Options
Preverification Options
General Options
Class Paths
File Names
File Filters
Filters
Overview of Keep Options
Keep Option Modifiers
Class Specifications

  二proguard主要三部分功能

         縮減程式碼、優化程式碼、混淆程式碼。三部分功能都可以在配置檔案裡配置不啟用此功能。

 #Shrink Options

#不縮減程式碼
-dontshrink


#Optimization Options
-dontoptimize

#Obfuscate Options 
#-不混淆輸入的類檔案 
#-dontobfuscate 

三用法

Class Specifications 類規範,詳細定義了類、介面、列舉、成員、方法等-keep options 和-assumenosideeffects option的保留規則。

   匹配符*在類、介面、列舉、成員、方法的使用方法。

   仔細閱讀

Filters

Overview of Keep Options

Keep Option Modifiers

Class Specifications

   1.在配置檔案中例如xml中引用到的類名,不能混淆重新命名。因為配置時需要通過配置檔案路徑載入類。

     android中的例如Activity的配置-keep public class * extends android.app.Activity(只保留類名,類名不會混淆重新命名,但是其成員和方法會混淆)

     在xml中出現的有Activity、Application、Service、BroadcastReceiver、ContentProvider、Fragment、Context、LinearLayout、View等自定義檢視。

   2.保留sdk系統自帶的一些內容。

-keepattributes Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,*Annotation*,EnclosingMethod

     比如-keepattributes *Annotation*會保留Activity的被@Override註釋的方法onCreate、onDestroy方法等。

   3.資源類變數需要保留

-keepclassmembers class **.R$* {
    public static <fields>;
}

   4.保留第三方jar包的所有類及其成員和方法,例如{ *;}匹配了類內的所有成員和方法。

#jar config
-dontwarn org.apache.log4j.**
-keep class org.apache.log4j.** { *;}

  5.預設情況下,proguard 會混淆所有程式碼,但是下面幾種情況是不能改變java 元素的名稱,否則就會這樣就會導致程式出錯。
一,我們用到反射的地方
二, 我們程式碼依賴於系統的介面,比如被系統程式碼呼叫的回撥方法,這種情況最複雜。
三, 是我們的java 元素名稱是在配置檔案中配置好的。

   6.對出現問題的類的處理。遇見一個及新增。

    -keep用法區別

1)保留某個類名不被混淆

-keep public class com.ebt.app.common.bean.Customer

2)保留類及其所有成員不被混淆

-keep public class com.ebt.app.common.bean.Customer { *;}

或者
-keepclasseswithmembers class com.ebt.app.common.bean.Customer {

    <init>;#匹配所有建構函式

    <fields>;#匹配所有成員
    <methods>;#匹配所有方法
}

3)只保留類名及其部分成員不被混淆

-keep public class com.ebt.app.common.bean.Customer { 

    static final<fields>;

    private void get*();

}

4)#保留包路徑下所有的類及其屬性和方法
-keep class com.ebt.app.sync.** { *;}

6.混淆後出現問題的除錯方法

  1)列印日誌,保留異常,原始檔行數資訊。

-printmapping out.map
-renamesourcefileattribute SourceFile
-keepattributes Exceptions,SourceFile

  2)確定哪一行哪個類出錯。

也可以使用Log或者System.out在可能出錯的行前後列印測試日誌,以確定具體出錯的類是哪一個。來決定是否保留。

http://blog.chengyunfeng.com/?p=545

   7.常見*的用法區別

修飾類、介面、列舉等時

* matches any part of a class name not containing the package separator. For example, "mypackage.*Test*" matches "mypackage.Test" and "mypackage.YourTestApplication", but not "mypackage.mysubpackage.MyTest". Or, more generally, "mypackage.*" matches all classes in "mypackage", but not in its subpackages.
** matches any part of a class name, possibly containing any number of package separators. For example, "**.Test" matches all Test classes in all packages except the root package. Or, "mypackage.**" matches all classes in "mypackage" and in its subpackages.
   修飾建構函式、成員變數、方法
  • Fields and methods are specified much like in Java, except that method argument lists don't contain argument names (just like in other tools like javadoc and javap). The specifications can also contain the following catch-all wildcards:
    <init> matches any constructor.
    <fields> matches any field.
    <methods> matches any method.
    * matches any field or method.
    Note that the above wildcards don't have return types. Only the <init> wildcard has an argument list.

    Fields and methods may also be specified using regular expressions. Names can contain the following wildcards:

    ? matches any single character in a method name.
    * matches any part of a method name.
    Types in descriptors can contain the following wildcards:
    % matches any primitive type ("boolean", "int", etc, but not "void").
    ? matches any single character in a class name.
    * matches any part of a class name not containing the package separator.
    ** matches any part of a class name, possibly containing any number of package separators.
    *** matches any type (primitive or non-primitive, array or non-array).
    ... matches any number of arguments of any type.
    Note that the ?*, and ** wildcards will never match primitive types. Furthermore, only the *** wildcards will match array types of any dimension. For example, "** get*()" matches "java.lang.Object getObject()", but not "float getFloat()", nor "java.lang.Object[] getObjects()".
  • Constructors can also be specified using their short class names (without package) or using their full class names. As in the Java language, the constructor specification has an argument list, but no return type.
  • The class access modifiers and class member access modifiers are typically used to restrict wildcarded classes and class members. They specify that the corresponding access flags have to be set for the member to match. A preceding ! specifies that the corresponding access flag should be unset.

    Combining multiple flags is allowed (e.g. public static). It means that both access flags have to be set (e.g. public and static), except when they are conflicting, in which case at least one of them has to be set (e.g. at least public or protected).

    ProGuard supports the additional modifiers syntheticbridge, and varargs, which may be set by compilers.


四常見例項

   http://proguard.sourceforge.net/index.html#/manual/examples.html

五總結常見的保留原則

   -keep options選項裡說明了一些要保留的選項。

六一個android apk 配置例項

#Shrink Options
#不縮減程式碼
-dontshrink

#Optimization Options
-dontoptimize
-optimizations !code/simplification/arithmetic
-allowaccessmodification

#Obfuscate Options 
#-不混淆輸入的類檔案 
#-dontobfuscate 
-printmapping out.map
-renamesourcefileattribute SourceFile
-keepattributes Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,*Annotation*,EnclosingMethod
-repackageclasses ''

# Add any project specific keep options here:
#Keep Options

<span style="color:#ff0000;">#android config</span>
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
-keep public class * extends android.app.Fragment
-keep public class * extends LinearLayout
-keep public class * extends android.view.View {
    public <init>(android.content.Context);
    public <init>(android.content.Context, android.util.AttributeSet);
    public <init>(android.content.Context, android.util.AttributeSet, int);
    public void set*(...);
}

-keepclasseswithmembers class * {
    public <init>(android.content.Context, android.util.AttributeSet);
}

-keepclasseswithmembers class * {
    public <init>(android.content.Context, android.util.AttributeSet, int);
}

-keepclassmembers class * extends android.content.Context {
   public void *(android.view.View);
   public void *(android.view.MenuItem);
}

-keepclassmembers class * implements android.os.Parcelable {
    static ** CREATOR;
}

-keepclassmembers class **.R$* {
    public static <fields>;
}

-keepclassmembers class * {
    @android.webkit.JavascriptInterface <methods>;
}

# Keep serializable classes and necessary members for serializable classes
# Copied from the ProGuard manual at http://proguard.sourceforge.net.
-keepnames class * implements java.io.Serializable
-keepclassmembers class * implements java.io.Serializable {
    static final long serialVersionUID;
    private static final java.io.ObjectStreamField[] serialPersistentFields;
    !static !transient <fields>;
    private void writeObject(java.io.ObjectOutputStream);
    private void readObject(java.io.ObjectInputStream);
    java.lang.Object writeReplace();
    java.lang.Object readResolve();
}

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
-keepclassmembers class fqcn.of.javascript.interface.for.webview {
   public *;
}

<span style="color:#ff0000;">#jar config</span>
-dontwarn org.apache.log4j.**
-keep class org.apache.log4j.** { *;}

-dontwarn com.baidu.oauth.**
-keep class com.baidu.oauth.** { *;}

-dontwarn org.achartengine.**
-keep class org.achartengine.** { *;}

-dontwarn net.sourceforge.jeval.**
-keep class net.sourceforge.jeval.** { *;}

-dontwarn de.greenrobot.dao.**
-keep class de.greenrobot.dao.** { *;}

-dontwarn org.wltea.expression.**
-keep class org.wltea.expression.** { *;}

-dontwarn org.apache.commons.net.**
-keep class org.apache.commons.net.** { *;}

-dontwarn com.baidu.pcs.**
-keep class com.baidu.pcs.** { *;}

-dontwarn de.mindpipe.android.logging.log4j.**
-keep class de.mindpipe.android.logging.log4j.** { *;}

-dontwarn com.google.gson.**
-keep class com.google.gson.** { *;}

-dontwarn com.google.**
-keep class com.google.** { *;}

-dontwarn org.apache.http.entity.mime.**
-keep class org.apache.http.entity.mime.** { *;}


<span style="color:#ff0000;">#special config</span>
-keep public class com.app.common.bean.CustomerData { *;}
#-keep public class com.app.common.bean.Customer { *;}
-keepclasseswithmembers class com.app.common.bean.Customer {
    <fields>;
    <methods>;
}
-keep public class com.app.common.bean.VRepositoryCategory {*;}