`

android源码使用proguard混淆编译及错误总结

 
阅读更多

 

关于混淆编译也主要是从网上学习的,决定对网上的进行总结,供大家一起学习,研究,东西主要都是网友们写的,我这里借鉴了,文章最后是网友的原文地址;

 

1,什么是混淆编译

 

ProGuard是一个免费的java类文件压缩,优化,混淆器.它探测并删除没有使用的类,字段,方法和属性.它删除没有用的说明并使用字节码得到最大优化.它使用无意义的名字来重命名类,字段和方法.

ProGuard的使用是为了:

1.创建紧凑的代码文档是为了更快的网络传输,快速装载和更小的内存占用.

2.创建的程序和程序库很难使用反向工程.

3.所以它能删除来自源文件中的没有调用的代码

4.充分利用java6的快速加载的优点来提前检测和返回java6中存在的类文件.

 

ProGuard支持那些种类的优化:

除了在压缩操作删除的无用类,字段和方法外,ProGuard也能在字节码级提供性能优化,内部方法有:

1 常量表达式求值

2 删除不必要的字段存取

3 删除不必要的方法调用

4 删除不必要的分支

5 删除不必要的比较和instanceof验证

6 删除未使用的代码

7 删除只写字段

8 删除未使用的方法参数

9 像push/pop简化一样的各种各样的peephole优化

10 在可能的情况下为类添加static和final修饰符

11 在可能的情况下为方法添加private, static和final修饰符

12 在可能的情况下使get/set方法成为内联的

13 当接口只有一个实现类的时候,就取代它

14 选择性的删除日志代码

实际的优化效果是依赖于你的代码和执行代码的虚拟机的。简单的虚拟机比有复杂JIT编译器的高级虚拟机更有效。无论如何,你的字节码会变得更小。

 

需要优化的不被支持技术: 

1 使非final的常量字段成为内联

2 像get/set方法一样使其他方法成为内联

3 将常量表达式移到循环之外

4 Optimizations that require escape analysis 

 

2,启动android中的混淆功能(关于eclipse中混淆,网上一大堆,这里不做解释)

     

 

在需要混淆的工程目录下(package/apps/下的工程)添加proguard.flags文件,该文件即为网络传说中的proguard.cfg,只是命名不一样而已,然后再Android.mk中添加如下两句:

LOCAL_PROGUARD_ENABLED := full

LOCAL_PROGUARD_FLAG_FILES := proguard.flags

上面的full 也可以是custom,如果不写这句,那还得添加如下一句:

TARGET_BUILD_VARIANT := user或者TARGET_BUILD_VARIANT := userdebug

这样后在工程目录下执行mm便可以看到在out目录下生成了形如proguard.classes.jar的东东,这就说明已在编译中启动了proguard

但反编译一看,并未出现网络云说的abcd替代符号,其实代码并未真正混淆:

android在编译时默认关闭了混淆选项,有去研究build/core目录的同志会发现这里也有个proguard.flags文件,其实在proguard的过程中,编译器会调用包括本地目录下和系统定义了的多个proguard.flags文件,而在这个文件中混淆的选项被禁止了,故而编译出来的apk仍未混淆。因此将如下句子注释掉便可实现真正的混淆编译:

# Don't obfuscate. We only need dead code striping.

-dontobfuscate(将该句加个#号注释掉)

 

好奇的同志还可以继续看看,为什么TARGET_BUILD_VARIANT := user和LOCAL_PROGUARD_ENABLED := full二选一即可,详见build/core/package.mk:

 

LOCAL_PROGUARD_ENABLED:=$(strip $(LOCAL_PROGUARD_ENABLED))

ifndef LOCAL_PROGUARD_ENABLED

ifneq ($(filter user userdebug, $(TARGET_BUILD_VARIANT)),)

# turn on Proguard by default for user & userdebug build

LOCAL_PROGUARD_ENABLED :=full

endif

endif

ifeq ($(LOCAL_PROGUARD_ENABLED),disabled)

# the package explicitly request to disable proguard.

LOCAL_PROGUARD_ENABLED :=

endif

proguard_options_file :=

ifneq ($(LOCAL_PROGUARD_ENABLED),custom)

ifneq ($(all_resources),)

proguard_options_file := $(package_expected_intermediates_COMMON)/proguard_options

endif # all_resources

endif # !custom

LOCAL_PROGUARD_FLAGS := $(addprefix -include ,$(proguard_options_file)) $(LOCAL_PROGUARD_FLAGS)

 

3,如何书写proguard.flags文件

 

参数解释:

-include {filename}    从给定的文件中读取配置参数

-basedirectory {directoryname}    指定基础目录为以后相对的档案名称

-injars {class_path}    指定要处理的应用程序jar,war,ear和目录

-outjars {class_path}    指定处理完后要输出的jar,war,ear和目录的名称

-libraryjars {classpath}    指定要处理的应用程序jar,war,ear和目录所需要的程序库文件

-dontskipnonpubliclibraryclasses    指定不去忽略非公共的库类。

-dontskipnonpubliclibraryclassmembers    指定不去忽略包可见的库类的成员。

保留选项

-keep {Modifier} {class_specification}    保护指定的类文件和类的成员

-keepclassmembers {modifier} {class_specification}    保护指定类的成员,如果此类受到保护他们会保护的更好

-keepclasseswithmembers {class_specification}    保护指定的类和类的成员,但条件是所有指定的类和类成员是要存在。

-keepnames {class_specification}    保护指定的类和类的成员的名称(如果他们不会压缩步骤中删除)

-keepclassmembernames {class_specification}    保护指定的类的成员的名称(如果他们不会压缩步骤中删除)

-keepclasseswithmembernames {class_specification}    保护指定的类和类的成员的名称,如果所有指定的类成员出席(在压缩步骤之后)

-printseeds {filename}    列出类和类的成员-keep选项的清单,标准输出到给定的文件

压缩

-dontshrink    不压缩输入的类文件

-printusage {filename}

-whyareyoukeeping {class_specification}    

优化

-dontoptimize    不优化输入的类文件

-assumenosideeffects {class_specification}    优化时假设指定的方法,没有任何副作用

-allowaccessmodification    优化时允许访问并修改有修饰符的类和类的成员

混淆

-dontobfuscate    不混淆输入的类文件

-printmapping {filename}

-applymapping {filename}    重用映射增加混淆

-obfuscationdictionary {filename}    使用给定文件中的关键字作为要混淆方法的名称

-overloadaggressively    混淆时应用侵入式重载

-useuniqueclassmembernames    确定统一的混淆类的成员名称来增加混淆

-flattenpackagehierarchy {package_name}    重新包装所有重命名的包并放在给定的单一包中

-repackageclass {package_name}    重新包装所有重命名的类文件中放在给定的单一包中

-dontusemixedcaseclassnames    混淆时不会产生形形色色的类名

-keepattributes {attribute_name,...}    保护给定的可选属性,例如LineNumberTable, LocalVariableTable, SourceFile, Deprecated, Synthetic, Signature, and InnerClasses.

-renamesourcefileattribute {string}    设置源文件中给定的字符串常量

 

4,实例(SkyvideoPlayer)

-optimizationpasses 3

-dontusemixedcaseclassnames

-dontskipnonpubliclibraryclasses

-verbose

-dontpreverify

-verbose

# The support library contains references to newer platform versions.

# Don't warn about those in case this app is linking against an older

# platform version.  We know about them, and they are safe.

-dontwarn

-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*

#by jiang

# -dontoptimize  #是否对类内部代码进行优化,默认优化

# Don't obfuscate. We only need dead code striping.

# -dontobfuscate  #不进行优化

#项目使用到的第三方jar包

-libraryjars ../libs/fastjson-1.1.23.jar

 

# removes such information by default, so configure it to keep all of it.

-keepattributes Signature   #不优化泛型和反射

 

#android默认项

-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.backup.BackupAgentHelper

-keep public class * extends android.preference.Preference

-keep public class com.android.vending.licensing.ILicensingService

 

# for skyworth fastjson

-keep class com.alibaba.fastjson.** { *; }

 

#以下为android默认项

-keepclasseswithmembernames class * {

    native ;

}

 

-keepclasseswithmembernames class * {

    public (android.content.Context, android.util.AttributeSet);

}

 

-keepclasseswithmembernames class * {

    public (android.content.Context, android.util.AttributeSet, int);

}

 

-keepclassmembers enum * {

    public static **[] values();

    public static ** valueOf(java.lang.String);

}

 

-keep class * implements android.os.Parcelable {

  public static final android.os.Parcelable$Creator *;

}

 

5,错误总结

 

问题一:使用gson包解析数据时,出现missing type parameter异常

程序中用到了gson的new typeToken,结果打包成apk发布时,发现抛出异常,但不通过打包apk时发现一切正常,百思不得其解,最初怀疑没有将gson-1.7.1.JAR打包进去,后来经过测试发现gson的其他方法经过打包也能正常运行,最后上网找了2天,终于在google gson论坛中找到了解决方法。

第一种:在 proguard.cfg中添加

-dontobfuscate

-dontoptimize

 

第二种:在 proguard.cfg中添加

# removes such information by default, so configure it to keep all of it.

-keepattributes Signature

 

# Gson specific classes

-keep class sun.misc.Unsafe { *; }

#-keep class com.google.gson.stream.** { *; }

 

# Application classes that will be serialized/deserialized over Gson

-keep class com.google.gson.examples.android.model.** { *; }

这两种方法都测试可行,第一个方法没有混淆编译,第二个方法能够混淆编译

问题二:

反射类不能进行混淆编译,需加入

-keep class com.test.model.response.** {*;}

问题三:

android辅助jar包异常,在proguard.cfg中加入

-dontwarn android.support.v4.**

-keep class android.support.v4.** {*;}

问题四:(同1)

类型转换错误,因为我用的泛型,所以在调用某些方法的时候,会出现这种错误,后面在混淆配置文件加了一个过滤泛型的语句,如下。

 

-keepattributes Signature

过后,就没有出现类似的类型转换错误。

 

问题五:空指针异常,这个错误是我对比前面的错误来说,所用的时间比较短,开始是找不到方法到底是哪个(原因是上面提到的混淆后方法名相同),所以就把这个类里面的所有方法都过滤掉,这样我没用多少时间,也就找到了具体的方法,可还是不明白原因,后面发现了其中的一个if判断,我利用反射筛选方法,关键字是“get”,突然我就震精了,大叫一声——soga,原来我 model的 set/get方法名全部都被混淆了,所以筛选不到方法,返回的也就是null值,自然下面用到这个方法的返回值就会抛出空指针异常。

 

解决方法:把 model包下面的所有类,全部过滤掉。

 

总结:如要用到反射,反射一般就会利用到泛型,所以必须要把泛型的全部过滤掉,如果有根据变量名或者方法名判断的,记得所在的类需过滤掉,之中还有用到 annotation的地方,要加入一行代码,如下:

 

-keepattributes *Annotation*

这样就能过滤掉所有的annotation,否则也会抛出空指针异常。

 

转载自:http://blog.sina.com.cn/s/blog_5f1ebb8f0101lkqz.html

推荐文章,内容都是他们写的,我只是整理了一下,呵呵

http://blog.csdn.net/hehe9737/article/details/8152330

 

http://charles-tanchao.diandian.com/post/2012-05-24/20118715

 

http://www.cnitblog.com/zouzheng/archive/2011/01/12/72639.html

 

http://www.eoeandroid.com/thread-173733-1-1.html

分享到:
评论

相关推荐

    ant proguard 混淆编译 之Eclipse-Idea

    NULL 博文链接:https://phenom.iteye.com/blog/745159

    使用Proguard混淆Java源代码

    java代码很容易被反编译,可通过混淆技术来保护源码,此处我们应用开源项目proguard来进行混淆。操作使用详见:http://blog.csdn.net/odian1/article/details/8282799

    ant proguard 混淆编译 之Netbeans

    NULL 博文链接:https://phenom.iteye.com/blog/734891

    利用混淆器ProGuard混淆java类,防止反编译

    NULL 博文链接:https://zochen.iteye.com/blog/682643

    JAVA源代码混淆器proguard4.8 + 安卓源码混淆配置文件(原创)

    proguard混淆器可以对多种平台的JAVA源代码进行混淆,增加反编译代价。proguard混淆器是开源的软件,压缩包内含全部最新版源代码。压缩包根目录下有我修改的安卓JAVA项目混淆配置文件,proguard自带的混淆配置文件在...

    Java防编译技术---proguard混淆器

    Java混淆技术,保护我们的源代码的安全性与技术保密性!

    java源代码混淆器proguard4.8 + 安卓源码混淆配置文件(原创)

    proguard混淆器可以对多种平台的JAVA源代码进行混淆,增加反编译代价。proguard混淆器是开源的软件,压缩包内含全部最新版源代码。压缩包根目录下有我修改的安卓JAVA项目混淆配置文件,proguard自带的混淆配置文件在...

    Android Java混淆(ProGuard)

    ProGuard是一个SourceForge上非常知名的开源项目。...为了很好的保护Java源代码,我们往往会对编译好的class文件进行混淆处理。ProGuard的主要作用就是混淆。当然它还能对字节码进行缩减体积、优化等。

    proguard 6.2.2魔改版

    proguard 6.2.2的魔改版本用于混淆app、jar、class等,将所有a,b,c等等的字符改成不可见字符,从而提高安全性。里面包括源码和编译好的jar包。编译源码使用core/build.sh,编译好的jar包在lib目录下。android app...

    proguard6.2.0.zip

    因为Java代码是非常容易反编码的,况且Android开发的应用程序是用Java代码写的,为了很好的保护Java源代码,我们需要对编译好后的class文件进行混淆。 ProGuard是一个混淆代码的开源项目,它的主要作用是混淆代码,...

    Android proguard用法详解

    为了很好的保护Java源代码,我们往往会对编译好的class文件进行混淆处理。ProGuard的主要作用就是混淆。当然它还能对字节码进行缩减体积、优化等,但那些对于我们来说都算是次要的功能。 引用ProGuard官方的一段话...

    Java代码混淆工具proguard

    经典的Java代码混淆工具,可以混淆class,jar类型的文件,防止被反编译,对需要进行源码保护的代码很有用。

    java源码混淆工具使用演示

    idea+maven+proguard,通过proguard实现源码的混淆编译,将源码的原始变量、方法名等按proguard规则进行统一修改替换,保证功能不变的情况下,一定程度提高源码的安全性,避免源码中的敏感词变量引起的安全检查异常...

    zxing.java源码解析-Confusion:Android代码混淆

    Android代码混淆 1.什么是代码混淆: Android SDK 自带了混淆工具Proguard。它位于SDK根目录\tools\proguard下面。如果开启了混淆, Proguard默认情况下会对所有代码,包括第三方包都进行混淆,可是有些代码或者第三...

    SpringBoot项目Jar包加密防止反编译详细讲解(值得珍藏)

    通过使用代码混淆和加密字节码等技术,可以有效地保护源代码的安全性,降低被恶意攻击的风险。然而,需要注意的是,混淆和加密并不能完全防止反编译,需要结合其他安全措施进行多层次防护。同时,也需要权衡加密对...

    详解Android的反编译和代码混淆

    代码混淆 要反编译apk需要下面3个工具 1、apktool(资源文件获取) 作用:资源文件获取,可以提取图片文件和布局文件进行使用查看 2、dex2jar(源文件获取) 作用:将APK反编译成java源码(classes.dex转化成jar文件) ...

    最新java jar包混淆工具

    java源码加密混淆技术 proguard,可以有效保护java源码

    基于Spring Boot和Vue的校园社团管理系统前后端分离设计源码

    项目共包含177个文件,其中编译后的Class文件56个,Java源代码文件55个,Vue组件文件15个,XML配置文件11个,JavaScript文件7个,Git忽略配置文件3个,项目配置文件2个,Markdown文档2个,以及Proguard混淆配置文件2...

    proguard:埃里克·拉福瑞(Eric LaFortune)的护卫镜

    Java字节码优化器和混淆器此分发包含以下目录: bin:运行ProGuard,其GUI和ReTrace的简单包装脚本lib:主要的jar,经过编译,可以与“ java -jar ....”一起使用示例:一些示例配置文件和项目它还包含源代码和构建...

    java8源码-GradleGuide:gradle的一些常识

    源语言编译成 Android 可读取的 Dalvik 可执行文件字节码, 且有其自己的 .jack 库格式,在一个工具中提供了大多数工具链功能:重新打包、压缩、模糊化以及 Dalvik 可执行文件分包。 以下是构建 Android Dalvik 可...

Global site tag (gtag.js) - Google Analytics