• Android 代码混淆


    什么是代码混淆

    Java 是一种跨平台的、解释型语言,Java 源代码编译成中间”字节码”存储于 class 文件中。由于跨平台的需要,Java 字节码中包括了很多源代码信息,如变量名、方法名,并且通过这些名称来访问变量和方法,这些符号带有许多语义信息,很容易被反编译成 Java 源代码。为了防止这种现象,我们可以使用 Java 混淆器对 Java 字节码进行混淆。

    混淆就是对发布出去的程序进行重新组织和处理,使得处理后的代码与处理前代码完成相同的功能。

    混淆后的代码很难被反编译,即使反编译成功也很难得出程序的真正语义。

    被混淆过的程序代码,仍然遵照原来的档案格式和指令集,执行结果也与混淆前一样,只是混淆器将代码中的所有变量、函数、类的名称变为简短的英文字母代号,在缺乏相应的函数名和程序注释的况下,即使被反编译,也将难以阅读。

    同时,混淆是不可逆的,在混淆的过程中一些不影响正常运行的信息将永久丢失,这些信息的丢失使程序变得更加难以理解。

    混淆器的作用不仅仅是保护代码,它也有精简编译后程序大小的作用。

    由于以上介绍的缩短变量和函数名以及丢失部分信息的原因, 编译后 jar 文件体积大约能减少25% ,这对当前费用较贵的无线网络传输是有一定意义的。

    混淆文件 proguard.cfg 参数详解 

     
    1. # 指定代码的压缩级别  
    2. -optimizationpasses 5  
    3.   
    4. # 是否使用大小写混合  
    5. -dontusemixedcaseclassnames  
    6.   
    7. # 是否混淆第三方jar  
    8. -dontskipnonpubliclibraryclasses  
    9.   
    10. # 混淆时是否做预校验  
    11. -dontpreverify  
    12.   
    13. # 混淆时是否记录日志  
    14. -verbose  
    15.   
    16. # 混淆时所采用的算法  
    17. -optimizations !code/simplification/arithmetic,!field/*,!class/merging/*  
    18.   
    19. # 保持哪些类不被混淆  
    20. -keep public class * extends android.app.Activity                                 
    21. -keep public class * extends android.app.Application                              
    22. -keep public class * extends android.app.Service                                  
    23. -keep public class * extends android.content.BroadcastReceiver                    
    24. -keep public class * extends android.content.ContentProvider                      
    25. -keep public class * extends android.app.backup.BackupAgentHelper                 
    26. -keep public class * extends android.preference.Preference                        
    27. -keep public class com.android.vending.licensing.ILicensingService      
    28.             
    29. # 保持 native 方法不被混淆  
    30. -keepclasseswithmembernames class * { native <methods>;}  
    31.   
    32. # 保持自定义控件类不被混淆  
    33. -keepclasseswithmembers class * {  
    34.  public <init>(android.content.Context, android.util.AttributeSet);  
    35. }  
    36.   
    37. # 保持自定义控件类不被混淆  
    38. -keepclasseswithmembers class * {  
    39.  public <init>(android.content.Context, android.util.AttributeSet, int);   
    40. }  
    41.   
    42. # 保持自定义控件类不被混淆  
    43. -keepclassmembers class * extends android.app.Activity {   
    44.  public void *(android.view.View);  
    45. }  
    46.   
    47. # 保持枚举 enum 类不被混淆  
    48. -keepclassmembers enum * {   
    49.  public static **[] values();  
    50.  public static ** valueOf(java.lang.String);  
    51. }  
    52.   
    53. # 保持 Parcelable 不被混淆  
    54. -keep class * implements android.os.Parcelable {   
    55.  public static final android.os.Parcelable$Creator *;  
    56. }  
    57.   
    58. # 保持自己定义的类不被混淆  
    59. -keep class MyClass;                                                              

     

    注(本人测试所得):1. 当使用此类配置后,再导出APK时通常会报许多红色的警告提示,此时,使用-ignorewarnings 忽略提示。

    2. 能正常导出成功,却不能运行的,通过查看日志,查找是哪些类引用出错,如以下错误信息 

     
    1. E/AndroidRuntime(19866): FATAL EXCEPTION: Thread-103  
    2. E/AndroidRuntime(19866): java.lang.ExceptionInInitializerError  
    3. E/AndroidRuntime(19866):    at com.a.a.a.b.b.a(Unknown Source)  
    4. E/AndroidRuntime(19866):    at tv.hisense.android.mps.service.ay.run(Unknown Source)  
    5. E/AndroidRuntime(19866): Caused by: b.a.a.c.b: The chosen LogFactory implementation does not extend LogFactory.  
    6.  Please check your configuration.   
    7. (Caused by java.lang.ClassCastException:   
    8. The application has specified that a custom LogFactory implementation should be used but Class  
    9. org.apache.commons.logging.impl.LogFactoryImpl cannot be converted to 'b.a.a.c.c'.   
    10. Please check the custom implementation.   
    11. Help can be found @http://commons.apache.org/logging/troubleshooting.html.)  
    12. E/AndroidRuntime(19866):    at b.a.a.c.c.a(Unknown Source)  
    13. E/AndroidRuntime(19866):    at b.a.a.c.e.run(Unknown Source)  
    14. E/AndroidRuntime(19866):    at java.security.AccessController.doPrivileged(AccessController.java:45)  
    15. E/AndroidRuntime(19866):    at b.a.a.c.c.a(Unknown Source)  
    16. E/AndroidRuntime(19866):    at b.a.a.c.c.a(Unknown Source)  
    17. E/AndroidRuntime(19866):    at b.a.a.c.c.b(Unknown Source)  
    18. E/AndroidRuntime(19866):    at b.a.a.b.p.<clinit>(Unknown Source)  
    19. E/AndroidRuntime(19866):    ... 2 more  

     

    提示以上信息可知
    org.apache.commons.logging.impl.LogFactoryImpl
    类引用出错,查找到此类所在的jar包,通过以下三句解决此问题  

     
    1. -libraryjars libs/commons-logging-1.1.1.jar    #忽略jar包  
    2. -dontwarn org.apache.**                        #不警告此包  
    3. -keep class org.apache.** {*;}                 #保留此包下代码不进行混淆   

    切记,一定要根据日志信息来确定忽略哪些jar包和保留哪些类,没出错的包就不要忽略和保留了,否则可能会产生OutOfMemoryError

     

    代码混淆的方法

    根据 SDK 的版本不同有 2 中不同的代码混淆方式,以上的 proguard.cfg 参数详解中所涉及到的信息是在较低版本SDK下的混淆脚本,事实上在高版本的SDK下混淆的原理和参数也与低版本的相差无几,只是在不同SDK版本的环境下引入混淆脚本的方式有所不同。具体方法如下:

    • 低版本 SDK 下,项目中同时包含 proguard.cfg 和 project.properties 文件,则只需在project.properties 文件末尾添加 proguard.config=proguard.cfg再将项目Export即可。
    • 高版本SDK下,项目中同时包含proguard-project.txt 和 project.properties 文件,这时需要在proguard-project.txt文件中进行如下信息的配置,然后再将项目Export即可。下面以真实的文件进行演示说明。 
     
    1. # This file is automatically generated by Android Tools.  
    2. # Do not modify this file -- YOUR CHANGES WILL BE ERASED!  
    3. #  
    4. # This file must be checked in Version Control Systems.  
    5. #  
    6. # To customize properties used by the Ant build system edit  
    7. "ant.properties", and override values to adapt the script to your  
    8. # project structure.  
    9. #  
    10. # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):  
    11. #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt  
    12.   
    13. proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt  
    14.   
    15. # 还可以使用项目内的配置文件  
    16. # proguard.config=proguard-project.txt  
    17.   
    18. # Project target.  
    19. target=android-19  

    以上的配置信息即是 project.properties 文件中内容,蓝色文字为我们在代码混淆过程中需要添加的配置信息,其中:sdk.dir 为你在当前机器上 SDK 的安装路径。如果想保留某个包下的文件不被混淆,可以在 proguard-project.txt 文件中加入保留对应包名的语句即可。

  • 相关阅读:
    1509 加长棒
    51Nod 1158 全是1的最大子矩阵
    P2953 [USACO09OPEN]牛的数字游戏Cow Digit Game
    P3384 【模板】树链剖分
    北京集训DAY3
    北京集训DAY2
    北京集训DAY1
    51Nod 1422 沙拉酱前缀 二分查找
    51Nod 1109 01组成的N的倍数
    51Nod 1043 幸运号码 数位DP
  • 原文地址:https://www.cnblogs.com/Free-Thinker/p/4666783.html
Copyright © 2020-2023  润新知