什么是代码混淆

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

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

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

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

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

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

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

混淆文件 proguard.cfg 参数详解

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

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

Android 代码混淆的更多相关文章

  1. Android代码混淆官方实现方法

    首先查看一下 “project.properties” 这个文件: # This file is automatically generated by Android Tools.# Do not m ...

  2. Android代码混淆和项目宣布步骤记录器

    原本放在一起Android项目与发布的文件相混淆.我突然想到,为什么不写博客,分享.有这篇文章的情况下,. Android代码混淆及项目公布步骤记录 一.清理代码中的调试信息,如Log.System. ...

  3. Android 代码混淆 混淆方案

    本篇文章:自己在混淆的时候整理出比较全面的混淆方法,比较实用,自己走过的坑,淌出来的路.请大家不要再走回头路,可能只要我们代码加混淆,一点不对就会导致项目运行崩溃等后果,有许多人发现没有打包运行好好地 ...

  4. Android代码混淆及项目发布方法记录

     Android代码混淆及项目发布步骤记录 本来整理了一份Android项目混淆与发布的文档,突然想到何不写篇博客,分享一下呢,如是便有了本文. Android代码混淆及项目发布步骤记录 一.清理 ...

  5. Android 代码混淆规则

    1. Proguard介绍 Android SDK自带了混淆工具Proguard.它位于SDK根目录toolsproguard下面.ProGuard是一个免费的Java类文件收缩,优化,混淆和预校验器 ...

  6. Android 代码混淆、第三方平台加固加密、渠道分发 完整教程(图文)

    第一步:代码混淆(注意引入的第三方jar) 在新版本的ADT创建项目时,混码的文件不再是proguard.cfg,而是project.properties和proguard-project.txt. ...

  7. Android 代码混淆 防止反编译

    为了防止代码被反编译,因此需要加入混淆.混淆也可以通过第三方进行apk混淆,也可以用android中的proguard进行混淆. 混淆步骤: 1.配置混淆文件,名字可以随意,在这里使用proguard ...

  8. android 代码混淆及问题大集锦

    最近在需要对所开发的项目进行了代码混淆,在android studio中开启代码混淆其实还是挺方便的,不过因为代码混淆产生的问题非常多,特别是对于一些涉及到反射的第三方库经常因为名称的变化导致无法使用 ...

  9. android代码混淆笔记

    混淆处理的apk被反编译后代码中包名类名等都变成abcd之类.非常难看懂. 使用代码混淆.启用混淆器,对相关文件进行编辑,然后打包签名就能够了: ------------ 在2.3的版本号中,项目中有 ...

随机推荐

  1. C函数调用与栈--代码真相

    前面详细的说了,C函数调用的过程中,栈的变化情况的原理部分,这里在看一下汇编代码的真正的实现. 有关前面的那一片博客,主要记住的就是函数调用时栈的变化,4+3+2的步骤: (1)设置栈帧边界 (2)开 ...

  2. apache加载php模块失败

    LoadModule php5_module "G:/php54/php5apache2_2.dll" apache2 conf加入这个之后无法加载 解决办法 在这句之前加入PHP ...

  3. javascript 检测密码强度

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  4. cocos2d-x游戏开发系列教程-超级玛丽07-CMGameMap(六)-马里奥跳跃

    当w键按下时,马里奥执行跳跃动作 执行跳跃动作也是在MarioMove函数中调用的

  5. 基于visual Studio2013解决C语言竞赛题之0403字符统计

      题目 解决代码及点评 这道题的目标是锻炼while循环,while循环的语法是 while(循环条件) { 循环体; } 每次进入循环体之前,先判断循环条件是否满足,如果不满足,执行序列就 ...

  6. zoj p3780 Paint the Grid Again

    地址:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5267 题意:Leo 有一个N*N 的格子,他又有一把魔法刷,这个刷子能把 ...

  7. OpenSSL命令---rand

    用途: 用来产生伪随机字节.随机数字产生器需要一个seed,先已经说过了,在没有/dev/srandom系统下的解决方法是自己做一个~/.rnd文件.如果该程序能让随机数字产生器很满意的被seeded ...

  8. Android 中 ListView Adapter getView 被多次调用问题 解决方法

    执行多次原因是因为每显示一个VIew,它都去测量view的高度,执行measure方法,导致getView执行多次. 解决方法是将 ListView 的 layout_width 设置为 fill_p ...

  9. 从java main方法说开去(转)

    刚刚接触java语言时,接触的便为一个java main方法.我们知道这样程序就可以运行了,但是程序是怎么运行起来的我们却不知道. 众所周知,当执行一个java程序时,首先会启动一个JVM虚拟机进程, ...

  10. Android常用动画Frame-By-Frame Animations的使用

    在Android的动画中有一种叫做Frame by Frame 的动画效果,就是跟Flash播放一样,是一帧一帧地显示,如果动画是连续并且有规律的话,就跟播放视频一样. 首先在drawable目录下添 ...