轉(zhuǎn):Android-Exception整理之com.google.gson.internal.xxx cannot be cast to xxx
1. 有時(shí)我們的Android使用Google的Gson庫摇展,在混淆后會(huì)報(bào)出一些異常:
java.lang.ClassCastException: com.google.gson.internal.StringMap cannot be cast to xxx
java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to xxx
這些異常往往是在配置混淆文件時(shí)出現(xiàn)的問題:
- 首先要確保混淆文件存在以下語句:
-keepattributes Signature
-keepattributes *Annotation*
-keep class sun.misc.Unsafe { *; }
-keep class com.google.gson.examples.android.model.** { *; }
- 另外(這往往是出現(xiàn)異常的原因)枫甲,確保自己項(xiàng)目?jī)?nèi)用到的實(shí)體類或者bean類(總之就是和Gson解析相關(guān)的模型類)有keep聲明:
# com.package.name是你的項(xiàng)目包名
-keep class com.package.name.bean.** { *; }
-keep class com.package.name.bean.entity.** { *; }
-keep public class com.package.name.R$*{
public static final int *;
}
2. Android引用第三方j(luò)ar包混淆時(shí)打包報(bào)錯(cuò)(can't find referenced class)
項(xiàng)目打包的時(shí)候,總是失敗目养,提示Proguard returned with error code 1. See console挂滓。然后看控制臺(tái)馒索,報(bào)出好多can't find referenced class......
- 場(chǎng)景:項(xiàng)目中引用了第三方的jar包
- 原因:第三方j(luò)ar包中引用了好多oracle發(fā)布的java標(biāo)準(zhǔn)中(也就是我們常用的JDK)包含的類,但是Android的java標(biāo)準(zhǔn)和oracle的不一樣红碑,android.jar里面去掉了oracle java標(biāo)準(zhǔn)中好多用不到的包和類;
- 解決辦法:
首先要把你項(xiàng)目中所引入的第三方j(luò)ar包使用"-libraryjars 包路徑"指定好舞吭。
然后泡垃,用
-dontwarn com.xx.bbb.**
-keep class com.xx.bbb.** { *;}
告訴proguard.cfg不用混淆指定的jar包,也不用提示這個(gè)包所報(bào)出的錯(cuò)羡鸥。
注意:要是用dontwarn取消指定包報(bào)錯(cuò)之前蔑穴,你要保證第三方引用的類在你的項(xiàng)目中沒有用到。
3. Android混淆后項(xiàng)目運(yùn)行的時(shí)候出現(xiàn)異常(混淆之前沒有該異常)
a. ClassNotFoundException惧浴,NoSuchMethodError
- 原因:這種異常會(huì)在好多情況下出現(xiàn)存和,比如:本地代碼通過反射調(diào)用其他的類,但是經(jīng)過了混淆之后衷旅,就會(huì)出現(xiàn)如上異常捐腿;調(diào)用了JNI之后,C或者C++和java代碼進(jìn)行交互的時(shí)候找不到j(luò)ava的類或者方法柿顶,導(dǎo)致發(fā)生了異常......等等茄袖,還有好多。
- 解決辦法:只需要將被調(diào)用的java類標(biāo)注為不混淆即可嘁锯。
-keep class package.classname{*;}
b. ExceptionInInitializerError
- 原因:這是由于類初始化的時(shí)候發(fā)生了異常宪祥。
- 解決辦法:找到具體是哪里的類哪個(gè)方法哪個(gè)類初始化的時(shí)候發(fā)生的異常,然后解決問題家乘。
- 注:遇到這個(gè)錯(cuò)誤蝗羊,首先要確認(rèn)是不是因?yàn)榈谌降膉ar包導(dǎo)致的。如果不是的話烤低,就找本地代碼肘交,看是不是寫的有問題。如果確實(shí)是因?yàn)榈谌絡(luò)ar包的代碼導(dǎo)致的扑馁,盡量找到源碼或者反編譯,查看問題到底是什么引起的凉驻,然后找到相應(yīng)的配置在proguard里面配置腻要。
- 例如:我們項(xiàng)目中碰到過一個(gè)問題,就是因?yàn)榈谌降膉ar包里面有一個(gè)字段初始化的時(shí)候報(bào)了空指針涝登,然后導(dǎo)致我們的代碼報(bào)了上面的錯(cuò)雄家。當(dāng)時(shí)很奇怪,為什么第三方的jar包還能報(bào)錯(cuò)胀滚,最后調(diào)查了之后才發(fā)現(xiàn)趟济,是因?yàn)槿思矣玫搅祟惖淖⒔猓鴓roguard在混淆優(yōu)化的時(shí)候把注解去掉了咽笼,所以報(bào)了空指針顷编,只需要在proguard里面加上保護(hù)注解就可以了-keepattributes Annotation--
c. ClassCastException
- 原因:類強(qiáng)制轉(zhuǎn)換的時(shí)候出錯(cuò)。
- 解決辦法:找到代碼剑刑,看是代碼寫的問題媳纬,還是混淆后的問題双肤。如果沒有混淆正常運(yùn)行的話,一般都是因?yàn)榛煜笥龅搅烁鞣N問題才報(bào)的錯(cuò)钮惠。我們項(xiàng)目中遇到的問題是因?yàn)闆]有讓proguard保持泛型茅糜,所以強(qiáng)轉(zhuǎn)的時(shí)候報(bào)錯(cuò)。只需要在proguard文件里面加上泛型即可-keepattributes Signature;
d. Resources$NotFoundException(resource not found)
- 原因:代碼進(jìn)行了混淆素挽,R文件沒有了蔑赘,所以通過反射獲取的R文件找不到, 資源沒有找到,是因?yàn)榈谌絡(luò)ar包或者自己的代碼是通過反射獲得R文件中的資源预明,所以需要將R文件屏蔽掉;
- 解決辦法:在proguard文件里設(shè)置不混淆R文件 -keep class *.R$ { *; }