Android中jsoup的混淆规则
版权声明:转载必须注明本文转自严振杰的博客:http://blog.yanzhenjie.comhtml
说实话这篇文章的标题和内容我以为很水,因此读者们要是也以为这篇文章很水的话,你顺着网线来打我啊。哈哈,不开个玩笑这文章都无法继续往下写了。java
这段时间天天工做到22点下班回家,到家后基本就23点了,周六周日也是同样的,因此Github上的项目有严重bug会在中午休息的时候抽时间修复,博客基本处于断更状态。不过庆幸的是昨晚已经把项目写完了,安排周一上线,今儿个是周日,终于能够休息了,也顺便把昨晚发现的一个关于jsoup的问题记录一下。node
发现问题
项目中使用了jsoup来分析html文档,一切都很顺利,可是在代码混淆后在某些手机上却发生了异常致使App崩溃。因而赶忙搜索了jsoup的混淆规则,发现千篇一概的规则是:spa
-dontwarn org.jsoup.**
-keep class org.jsoup.**{*;}
1
2
这样的混淆规则不用试就知道确定是能够解决问题的,可是把至关于把部分代码暴露了出去,因而我抓了下崩溃日志,最主要的地方以下:.net
Caused by: java.lang.ExceptionInInitializerError
at org.a.c.f$a.<init>(SourceFile:372)
at org.a.c.f.<init>(SourceFile:19)
at org.a.d.m.b(SourceFile:32)
at org.a.d.m.a(SourceFile:42)
at org.a.d.b.a(SourceFile:56)
at org.a.d.g.ay(SourceFile:100)
at org.a.a.hm(SourceFile:58)日志
Caused by: java.lang.IllegalStateException:
Could not read resource entities-xhtml.properties.
Make sure you copy resources for org.a.c.i
at org.a.c.i.a(SourceFile:301)
at org.a.c.i.b(SourceFile:25)
at org.a.c.i$b.<init>(SourceFile:53)
at org.a.c.i$b.<clinit>(SourceFile:34)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
经过下面这句话能够判断是jsoup抛出的异常没跑了:htm
Caused by: java.lang.ExceptionInInitializerError
at org.a.c.f$a.<init>(SourceFile:372)
1
2
而后目光迅速被吸引到这句话:blog
Could not read resource entities-xhtml.properties
1
哦这下明白了,原来是某个类中读取了entities-xhtml.properties资源文件,混淆以后读不出来了。凭经验来分析一下,假若有一个类叫A,那么java中读取资源文件咱们通常是:资源
A.class.getResourceAsStream("fileName");
1
而class.getResourceAsStream(String)会指定要加载的资源路径与当前类所在包的路径一致。例如咱们写了一个A类在包com.yanzhenjie.test下,那么A.class.getResourceAsStream("fileName") 会在com.yanzhenjie.test包下查找相应的资源。若是这个fileName是以/开头的,那么就会从classpath的根路径下开始查找。开发
注:此资源非彼资源文件,只涉猎Android开发的同窗不要把这个资源文件和Android中/res下的资源文件混淆,不是同一个东西。
因此如今问题基本上已经浮出水面了,作了代码混淆以后,因为规则外的class文件和路径所有被混淆,而资源文件的路径不会被混淆,打包成apk后,class文件在apk/classes.dex中,classes.dex反编译成jar文件,jar文件再解压后class文件的路径会变成a.b.c.className,而资源文件在/apk/packageName下,它们的路径由于没有混淆仍是com.yanzhenjie.test.fileName。所以class文件的路径是a.b.c.className,而资源文件的路径是com.yanzhenjie.test.fileName因此class.getResourceAsStream(String)会加载不到资源文件,剩下的就是看源码找出资源文件和class所在包并添加混淆规则了。
java包图:
根据上面的异常信息和包中的资源文件entities-xxx.properties判断下,大概加载资源文件的代码应该在Entities.class中吧,因而咱们打开Entities.class文件,果真发现了报异常的代码:
再往下翻一点就能够看到一个枚举类,咱们知道枚举至关因而常量。因此下图中类Entities被load的时候枚举EscapeMode的几个成员值就要初始化了,初始化即走本身的构造方法,在构造方法中又调用了上图中加载资源文件的代码:
由于咱们发现问题是咱们混淆了Entities.class所在包名致使的异常,因此咱们只要保证这个包名不被混淆便可。
解决方案
最开始说的比较通用的混淆规则确定是能够解决问题的:
-dontwarn org.jsoup.**
-keep class org.jsoup.**{*;}
1
2
可是这至关于没有混淆jsoup了,这里咱们能够维持包名不混淆便可解决问题,咱们只须要为jsoup添加以下混淆规则便可:
-keeppackagenames org.jsoup.nodes1我这样写能够解决我遇到的这个问题,若是其它人还遇到其它问题,能够在博客下方留言,我会给出解决方案。本文结束,一边带孩子一边写博客,写完了专心哄孩子去了,白白。————————————————版权声明:本文为CSDN博主「严振杰」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处连接及本声明。原文连接:https://blog.csdn.net/yanzhenjie1003/article/details/78384725