简介

Java代码是非常容易反编译的。为了很好的保护Java源代码,我们往往会对编译好的class文件进行混淆处理。

ProGuard是一个混淆代码的开源项目。它的主要作用就是混淆,当然它还能对字节码进行缩减体积、优化等,但那些对于我们来说都算是次要的功能。官网网址是:

http://proguard.sourceforge.net/。

详解

1、原理

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

混淆就是对发布出去的程序进行重新组织和处理,使得处理后的代码与处理前代码完成相同的功能,而混淆后的代码很难被反编译,即使反编译成功也很难得出程序的真正语义。被混淆过的程序代码,仍然遵照原来的档案格式和指令集,执行结果也与混淆前一样,只是混淆器将代码中的所有变量、函数、类的名称变为简短的英文字母代号,在缺乏相应的函数名和程序注释的况下,即使被反编译,也将难以阅读。同时混淆是不可逆的,在混淆的过程中一些不影响正常运行的信息将永久丢失,这些信息的丢失使程序变得更加难以理解。

混淆器的作用不仅仅是保护代码,它也有精简编译后程序大小的作用。由于以上介绍的缩短变量和函数名以及丢失部分信息的原因, 编译后 jar 文件体积大约能减少25% ,这对当前费用较贵的无线网络传输是有一定意义的。

2、语法
[java] view plaincopy
  1. -include {filename}    从给定的文件中读取配置参数
  2. -basedirectory {directoryname}    指定基础目录为以后相对的档案名称
  3. -injars {class_path}    指定要处理的应用程序jar,war,ear和目录
  4. -outjars {class_path}    指定处理完后要输出的jar,war,ear和目录的名称
  5. -libraryjars {classpath}    指定要处理的应用程序jar,war,ear和目录所需要的程序库文件
  6. -dontskipnonpubliclibraryclasses    指定不去忽略非公共的库类。
  7. -dontskipnonpubliclibraryclassmembers    指定不去忽略包可见的库类的成员。
  8. 保留选项
  9. -keep {Modifier} {class_specification}    保护指定的类文件和类的成员
  10. -keepclassmembers {modifier} {class_specification}    保护指定类的成员,如果此类受到保护他们会保护的更好
  11. -keepclasseswithmembers {class_specification}    保护指定的类和类的成员,但条件是所有指定的类和类成员是要存在。
  12. -keepnames {class_specification}    保护指定的类和类的成员的名称(如果他们不会压缩步骤中删除)
  13. -keepclassmembernames {class_specification}    保护指定的类的成员的名称(如果他们不会压缩步骤中删除)
  14. -keepclasseswithmembernames {class_specification}    保护指定的类和类的成员的名称,如果所有指定的类成员出席(在压缩步骤之后)
  15. -printseeds {filename}    列出类和类的成员-keep选项的清单,标准输出到给定的文件
  16. 压缩
  17. -dontshrink    不压缩输入的类文件
  18. -printusage {filename}
  19. -whyareyoukeeping {class_specification}
  20. 优化
  21. -dontoptimize    不优化输入的类文件
  22. -assumenosideeffects {class_specification}    优化时假设指定的方法,没有任何副作用
  23. -allowaccessmodification    优化时允许访问并修改有修饰符的类和类的成员
  24. 混淆
  25. -dontobfuscate    不混淆输入的类文件
  26. -printmapping {filename}
  27. -applymapping {filename}    重用映射增加混淆
  28. -obfuscationdictionary {filename}    使用给定文件中的关键字作为要混淆方法的名称
  29. -overloadaggressively    混淆时应用侵入式重载
  30. -useuniqueclassmembernames    确定统一的混淆类的成员名称来增加混淆
  31. -flattenpackagehierarchy {package_name}    重新包装所有重命名的包并放在给定的单一包中
  32. -repackageclass {package_name}    重新包装所有重命名的类文件中放在给定的单一包中
  33. -dontusemixedcaseclassnames    混淆时不会产生形形色色的类名
  34. -keepattributes {attribute_name,...}    保护给定的可选属性,例如LineNumberTable, LocalVariableTable, SourceFile, Deprecated, Synthetic, Signature, and
  35. InnerClasses.
  36. -renamesourcefileattribute {string}    设置源文件中给定的字符串常量

demo 实例

[java] view plaincopy
  1. -ignorewarnings                     # 忽略警告,避免打包时某些警告出现
  2. -optimizationpasses 5               # 指定代码的压缩级别
  3. -dontusemixedcaseclassnames         # 是否使用大小写混合
  4. -dontskipnonpubliclibraryclasses    # 是否混淆第三方jar
  5. -dontpreverify                      # 混淆时是否做预校验
  6. -verbose                            # 混淆时是否记录日志
  7. -optimizations !code/simplification/arithmetic,!field/*,!class/merging/*        # 混淆时所采用的算法
  8. -libraryjars   libs/treecore.jar
  9. -dontwarn android.support.v4.**     #缺省proguard 会检查每一个引用是否正确,但是第三方库里面往往有些不会用到的类,没有正确引用。如果不配置的话,系统就会报错。
  10. -dontwarn android.os.**
  11. -keep class android.support.v4.** { *; }        # 保持哪些类不被混淆
  12. -keep class com.baidu.** { *; }
  13. -keep class vi.com.gdi.bgl.android.**{*;}
  14. -keep class android.os.**{*;}
  15. -keep interface android.support.v4.app.** { *; }
  16. -keep public class * extends android.support.v4.**
  17. -keep public class * extends android.app.Fragment
  18. -keep public class * extends android.app.Activity
  19. -keep public class * extends android.app.Application
  20. -keep public class * extends android.app.Service
  21. -keep public class * extends android.content.BroadcastReceiver
  22. -keep public class * extends android.content.ContentProvider
  23. -keep public class * extends android.support.v4.widget
  24. -keep public class * extends com.sqlcrypt.database
  25. -keep public class * extends com.sqlcrypt.database.sqlite
  26. -keep public class * extends com.treecore.**
  27. -keep public class * extends de.greenrobot.dao.**
  28. -keepclasseswithmembernames class * {       # 保持 native 方法不被混淆
  29. native <methods>;
  30. }
  31. -keepclasseswithmembers class * {            # 保持自定义控件类不被混淆
  32. public <init>(android.content.Context, android.util.AttributeSet);
  33. }
  34. -keepclasseswithmembers class * {            # 保持自定义控件类不被混淆
  35. public <init>(android.content.Context, android.util.AttributeSet, int);
  36. }
  37. -keepclassmembers class * extends android.app.Activity { //保持类成员
  38. public void *(android.view.View);
  39. }
  40. -keepclassmembers enum * {                  # 保持枚举 enum 类不被混淆
  41. public static **[] values();
  42. public static ** valueOf(java.lang.String);
  43. }
  44. -keep class * implements android.os.Parcelable {    # 保持 Parcelable 不被混淆
  45. public static final android.os.Parcelable$Creator *;
  46. }
  47. -keep class MyClass;                              # 保持自己定义的类不被混淆
3、文件

在release模式下打包apk时会自动运行ProGuard,这里的release模式指的是通过ant release命令或eclipse project->android tools->export signed(unsigned) 
application package生成apk。
在debug模式下为了更快调试并不会调用proguard。
 
如果是ant命令打包apk,proguard信息文件会保存于<project_root>/bin/proguard文件夹内;
如果用eclipse export命令打包,会在<project_root>/proguard文件夹内。其中包含以下文件:

mapping.txt
表示混淆前后代码的对照表,这个文件非常重要。如果你的代码混淆后会产生bug的话,log提示中是混淆后的代码,希望定位到源代码的话就可以根据mapping.txt反推。
每次发布都要保留它方便该版本出现问题时调出日志进行排查,它可以根据版本号或是发布时间命名来保存或是放进代码版本控制中。

dump.txt
描述apk内所有class文件的内部结构。

seeds.txt
列出了没有被混淆的类和成员。

usage.txt
列出了源代码中被删除在apk中不存在的代码。

4、不能混淆的代码

顾名思义,不能混淆代码,否则会出错。

1、放射的地方

2、系统接口

3、Jni接口

4、

android.app.backup.BackupAgentHelper
android.preference.Preference

com.android.vending.licensing.ILicensingService

……

5、bug(常见错误)
1、Proguard returned with error code 1. See console

1、更新proguard版本  
2、android-support-v4 不进行混淆

3、添加缺少相应的库

2、使用gson包解析数据时,出现missing type parameter异常

1、在 proguard.cfg中添加

[java] view plaincopy
  1. -dontobfuscate
  2. -dontoptimize

2、在 proguard.cfg中添加

[java] view plaincopy
  1. # removes such information by default, so configure it to keep all of it.
  2. -keepattributes Signature
  3. # Gson specific classes
  4. -keep class sun.misc.Unsafe { *; }
  5. #-keep class com.google.gson.stream.** { *; }
  6. # Application classes that will be serialized/deserialized over Gson
  7. -keep class com.google.gson.examples.android.model.** { *; }
3、类型转换错误

-keepattributes Signature

4、空指针异常

混淆过滤掉相关类与方法

5、安卓代码混淆与反射冲突,地图无法显示等问题解决及反编译方法,安卓反编译

此前的代码混淆,因为并没有用到反射,所以常规的代码混淆方式一遍就能通过,而此项目中某些类利用到了反射机制(本人的这个项目中有即时通讯功能,所以有表情类资源,因此需要通过反射由文件名找到表情资源id),当由文件名去寻找资源id时就报空指针异常了,期初我并不知道什么原因,通过反编译已经混淆的apk,一步一步寻找到出错的地方,才恍然大悟,正是反射那一步出现了问题:Field field = R.drawable.class.getDeclaredField(name);走到这一步就挂了,程序直接崩溃。

解决办法:
   1.在proguard.cfg文件中,将反射用到的类中的变量不被混淆:
   如:-keep public class com.byl.bean.Expressions { *; },表示Expressions 这个类及类中的所有变量及方法不被混淆,注意要写全路径;
   2.过滤泛型:-keepattributes Signature
   3.最重要的一点:保持R文件不被混淆,否则,你的反射是获取不到资源id的:-keep class **.R$* {*;}

补充一下:上个问题解决后,接下来又遇到了一个问题就是混淆后,地图无法正常使用了,博主使用的是百度地图,在proguard.cfg也已经写明了:
-keep class com.baidu.**   {*;}
-keep class vi.com.**   {*;}

6、android.provider.Settings$Global

# Project target.
target=android-19

7、java.lang.reflect.UndeclaredThrowableException

-keep interface com.dev.impl.**

8、内存溢出和无法写入堆栈

javaOptions in proguard := Seq(...)
or
javaOptions in (Proguard, proguard) := Seq(...)

9、Error: Unable to access jarfile ..\lib\proguard.jar

路径问题

10、java.lang.NoSuchMethodError

没有相关方法,方法被混淆了,混淆过滤掉相关方法便可。

11、专业网站bug解决方法

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

总结

有了混淆技术,代码再也不用担心被偷了…

android 代码混淆相关推荐

  1. android aidl混淆代码,Android代码混淆

    什么是代码混淆 代码混淆就是将代码中的各种元素,如变量,方法,类和包的名字改写成无意义的名字,增加项目反编译后被读懂的难度. Android代码混淆使用ProGuard工具,ProGuard是一个压缩 ...

  2. android代码混淆个人总结及踩坑

    android代码混淆个人总结及踩坑 前言 公司项目使用组件化开发的形式,需要对自己负责的模块进行一些混淆配置,关于混淆相信做android开发的都或多或少有过一些接触,通过对混淆文件的配置从而将代码 ...

  3. android 混淆后的机制,Android 代码混淆机制

    Android 代码混淆机制 由于Android项目是基于java语言的,而java属于高层抽象语言,易于反编译,其编译后的程序包包含了大量的源代码变量.函数名.数据结构等信息,根据其编译打包后的AP ...

  4. android加密墙,Android代码混淆加密配置(Proguard文件解析)

    Android代码混淆加密配置(Proguard文件解析) Android代码混淆加密配置(Proguard文件解析) 为了防止自己的APP被轻易反编译,我们需要对APK进行混淆,或者特殊加密处理.可 ...

  5. android混淆语法(android代码混淆工具)

    android 代码混淆算法有哪些 根据SDK的版本不同有2中不同的代码混淆方式,以上的proguard.cfg参数详解中所涉及到的信息是在较低版本SDK下的混淆脚本,事实上在高版本的SDK下混淆的原 ...

  6. Android 代码混淆语法讲解及常用模板(转)

    转载请注明原博客地址  Android 代码混淆语法讲解及常用模板 前言 混淆对于每一个开发者来说都不陌生,对于大多数 APP 而言,在上线之前,通常会进行代码混淆,加固,防止自己的 APP 被别人轻 ...

  7. Android代码混淆配置说明

    1.为什么需要代码混淆 Proguard混淆用于保护APP不被破解和逆向分析,Proguard通过移除没有用到的代码以及通过特定规则重命名类.变量.方法来压缩.优化.混淆你的代码.这样可以让你APK更 ...

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

    首先查看一下 "project.properties" 这个文件: # This file is automatically generated by Android Tools. ...

  9. 使用ProGuard进行Android代码混淆(保姆级教程)

    使用ProGuard进行Android代码混淆(保姆级教程) 一.ProGuard的功能 ProGuard是一个混淆代码的开源项目,主要是用来对java代码进行混淆,当然也就可以对java代码进行混淆 ...

  10. Android代码混淆后的定位

    Android代码混淆后的定位 什么是代码混淆 如何开启Android Studio的代码混淆 如何在程序奔溃后定位到奔溃的代码行 mapping.txt 分析流程 什么是代码混淆 在java写的.j ...

最新文章

  1. WPF 与Surface 2.0 SDK 亲密接触 - ScatterView 篇
  2. javase基础-Helloword
  3. P(Y=y|x;θ)表示什么意思
  4. 一招让你彻底掌握C语言中运用宏以及#与##的妙用
  5. 企业内部信息化项目管理之我所见
  6. 4.OD-调试示例1
  7. Python 多进程pool.map()方法的使用
  8. golang 释放内存机制的探索
  9. SQL Server常用约束表达式实例
  10. Linux学习总结(19)——Linux中文本编辑器vim特殊使用方法
  11. 【问题解决方案】谷歌浏览器如何打开“开发者工具”窗口
  12. 【优化预测】基于matlab飞蛾扑火算法优化LSSVM预测【含Matlab源码 142期】
  13. Charles破解和安装【破解APP抓包限制】Xposed+JustTrustMe关闭SSL证书验证
  14. 密码学 ZUC算法 Python实现
  15. [资源分享][Unity][人物模型][动作]一些人物模型以及动作的分享
  16. 2023湖北大学考研分析
  17. 计算机中丢失storm.d,WIN7更新错误8024200D的解决方法
  18. 看起来比较舒服的背景颜色值
  19. java命令执行jar包main方法指定相关依赖
  20. 数据库第一范式(图解)

热门文章

  1. 怎么修改云服务器,怎么修改云服务器的登录密码
  2. 合并k个有序链表 python_Leetcode打卡 | No.23 合并 k 个有序链表
  3. 玩vr游戏的计算机配置要求,你的电脑能玩VR游戏吗?合格电脑不足1%
  4. python中使用tomorrow多线程时报错invalid syntax
  5. 名悦集团分享那些省钱又简单的汽车保养妙招
  6. Markdown入门学习小结
  7. canvas制作动态文字颗粒动画
  8. 洛谷题单1-7 搜索题解
  9. 极客时间--数据结构与算法之美
  10. 使用Guardium和WebSphere Application Server监视应用程序用户的数据库活动