日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

ProGuard常见问题及解决套路

發(fā)布時(shí)間:2023/12/14 编程问答 48 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ProGuard常见问题及解决套路 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

ProGuard是一個(gè)壓縮、優(yōu)化和混淆Java字節(jié)碼的工具,非常好用。本篇文章總結(jié)一下許多人在使用ProGuard時(shí)經(jīng)常遇到的問題。

我把在使用ProGuard時(shí)經(jīng)常遇到的問題分為兩類,分別是導(dǎo)致構(gòu)建失敗的編譯時(shí)問題,以及構(gòu)建通過(guò)但運(yùn)行時(shí)崩潰或結(jié)果不正確的運(yùn)行時(shí)問題。大多數(shù)人所遇到的大多數(shù)問題,都可以在下面的內(nèi)容中找到對(duì)應(yīng)的解決套路。
在開始講這兩類問題前,先明確一點(diǎn):我們所說(shuō)的添加混淆規(guī)則,不是指加入了才會(huì)混淆相關(guān)的類,相反,事實(shí)上,當(dāng)你啟用混淆之后,添加的一些諸如-keep xxxx的規(guī)則才是起著不混淆的作用。
下面開始講這兩類問題。

編譯時(shí)問題

問題

首先講編譯時(shí)的問題。導(dǎo)致編譯不通過(guò),最常見的情況是這樣的:
在漫長(zhǎng)的編譯之后,我們等到的控制臺(tái)上的這樣一個(gè)輸出結(jié)果:

... Note: there were 8 references to unknown classes.You should check your configuration for typos.(http://proguard.sourceforge.net/manual/troubleshooting.html#unknownclass) Note: there were 272 unkept descriptor classes in kept class members.You should consider explicitly keeping the mentioned classes(using '-keep').(http://proguard.sourceforge.net/manual/troubleshooting.html#descriptorclass) Note: there were 75 unresolved dynamic references to classes or interfaces.You should check if you need to specify additional program jars.(http://proguard.sourceforge.net/manual/troubleshooting.html#dynamicalclass) Warning: there were 11 unresolved references to classes or interfaces.You may need to add missing library jars or update their versions.If your code works fine without the missing classes, you can suppressthe warnings with '-dontwarn' options.(http://proguard.sourceforge.net/manual/troubleshooting.html#unresolvedclass) Warning: Exception while processing task java.io.IOException: Please correct the above warnings first.

原因及解決方法

有些小伙伴會(huì)自動(dòng)忽略英文日志,即便它給出了明確的答案,這是個(gè)嚴(yán)重的不良習(xí)慣。如上,其實(shí)在這段日志中,已經(jīng)表明了原因及解決方案了。注意Warning開頭的警告內(nèi)容,最后一個(gè)警告是讓你先解決第一個(gè)警告的內(nèi)容,所以先忽略。我們看它前面的警告:

there were 11 unresolved references to classes or interfaces.You may need to add missing library jars or update their versions.If your code works fine without the missing classes, you can suppressthe warnings with '-dontwarn' options.

這是什么意思呢?
第一句話是告訴你原因:有11個(gè)未解析的類或引用
后面兩句是解決方案。方案一:你可能需要添加丟失的庫(kù)或更新它們的版本。方案二:如果你現(xiàn)在代碼運(yùn)行得好好的,也就是沒有它們也沒關(guān)系,那你可以使用-dontwarn來(lái)禁止這樣的警告。

那么如何知道有哪些未解析的類或引用呢?
遇到這樣的問題,很簡(jiǎn)單,我們往上翻,最終肯定會(huì)找到Warning開頭的日志內(nèi)容:

Warning: okhttp3.internal.platform.ConscryptPlatform: can't find referenced class org.conscrypt.OpenSSLProvider Warning: okhttp3.internal.platform.ConscryptPlatform: can't find referenced class org.conscrypt.OpenSSLProvider Warning: okhttp3.internal.platform.ConscryptPlatform: can't find referenced class org.conscrypt.Conscrypt Warning: okhttp3.internal.platform.ConscryptPlatform: can't find referenced class org.conscrypt.Conscrypt Warning: okhttp3.internal.platform.ConscryptPlatform: can't find referenced class org.conscrypt.Conscrypt Warning: okhttp3.internal.platform.ConscryptPlatform: can't find referenced class org.conscrypt.Conscrypt Warning: okhttp3.internal.platform.ConscryptPlatform: can't find referenced class org.conscrypt.Conscrypt Warning: okhttp3.internal.platform.ConscryptPlatform: can't find referenced class org.conscrypt.Conscrypt Warning: okhttp3.internal.platform.ConscryptPlatform: can't find referenced class org.conscrypt.Conscrypt Warning: okhttp3.internal.platform.ConscryptPlatform: can't find referenced class org.conscrypt.Conscrypt Warning: okhttp3.internal.platform.ConscryptPlatform: can't find referenced class org.conscrypt.Conscrypt

它的句型是這樣的:Warning: xxxx.xxx.ABC: can't find referenced class xxx.xxx.XYZ
意思就是第三方庫(kù)里的ABC引用了XYZ這個(gè)類,但是我在類路徑中找不到XYZ這個(gè)類。
這種情況很常見,比如一個(gè)Java庫(kù)使用了另一個(gè)庫(kù)的一些類來(lái)實(shí)現(xiàn)某個(gè)特性。如果你在使用這個(gè)庫(kù)的時(shí)候需要這個(gè)特性,那么你就要把另一個(gè)庫(kù)也加進(jìn)來(lái),也就是前面給出的方案一。而如果你不需要用到,如上面的例子,項(xiàng)目中實(shí)際上用不到org.conscrypt包里的內(nèi)容,那么我們?cè)诨煜?guī)則的文件中添加上-dontwarn規(guī)則就可以了。

如何添加?

規(guī)則很簡(jiǎn)單。

-dontwarn 類名

在上面的日志中,有引用的類,也有被引用的類,這兩者都可以。也就是對(duì)于前面的句型,你既可以使用-dontwarn xxxx.xxx.ABC,也可以使用-dontwarn xxx.xxx.XYZ。
比如上面的例子,我們用

-dontwarn okhttp3.internal.platform.ConscryptPlatform

和用

-dontwarn org.conscrypt.OpenSSLProvider -dontwarn org.conscrypt.Conscrypt

都可以解決問題。但從這里也可以看出疑惑來(lái)了。如果有多個(gè)類呢?是不是每一個(gè)類都要寫上去呢?
當(dāng)然不是。這里的類名是支持通配符的,比如上面,我們可以寫為:

-dontwarn org.conscrypt.*

表示禁止org.conscrypt包下的類的警告。但是這里的*是不包含包分隔符的,也就是說(shuō)它的子包里面的類是不會(huì)被禁止的。如果需要連它下面的包的類也一并禁止,可以使用包含包分隔符的**,也就是如下:

-dontwarn org.conscrypt.**

關(guān)于過(guò)濾器的更多用法,可以參閱文檔:https://www.guardsquare.com/en/products/proguard/manual/usage#filters

總結(jié)

這是最常見的一類問題,我們來(lái)總結(jié)一下這個(gè)套路:

  • 編譯報(bào)錯(cuò),提示內(nèi)容是Warning: there were xxx unresolved references to classes or interfaces.。
  • 往上找?guī)в蠾arning:的日志,句型結(jié)構(gòu)為:Warning: xxxx.xxx.ABC: can't find referenced class xxx.xxx.XYZ
  • 往混淆規(guī)則里添加-dontwarn 類名的規(guī)則。
  • 運(yùn)行時(shí)問題

    我們?cè)賮?lái)看另一類問題。
    當(dāng)有人在討論群里求助混淆相關(guān)的問題時(shí),往往會(huì)有人說(shuō)加-keep。那么-keep是作什么用呢?在什么情況下需要它呢?

    在文章開頭一句話介紹過(guò),Proguard 是一個(gè)壓縮、優(yōu)化和混淆Java字節(jié)碼文件的工具。也就是,它所做的不僅僅包括我們所知道的混淆,它會(huì)分析所有的類,找出沒有用的類、字段、方法等把它們刪除掉,從而達(dá)到對(duì)字節(jié)碼的壓縮及優(yōu)化。而如果我們使用了反射去調(diào)用一些類或方法的話,它是不知道的,這樣就會(huì)導(dǎo)致“誤刪”的情況。
    所以當(dāng)開啟混淆之后,出現(xiàn)類找不到,方法找不到,屬性找不到時(shí),我們就要使用keep相關(guān)規(guī)則來(lái)把它們給留住啦。比如使用-keep class xxxx {*;}保留指定的類名及其成員。
    keep規(guī)則有三種(Android新增加的@keep注解不談,這里只講規(guī)則文件的內(nèi)容):

    • -keep 保留指定的類名及其成員
    • -keepclassmembers 只保留住成員,不能保留住類名
    • -keepclasseswithmembers 根據(jù)成員找到滿足條件的所有類,保留它們的類名和成員名

    比如我們使用了事件總線,為使方法能保留,我們可以添加如下的規(guī)則:

    -keepclassmembers class ** {@org.greenrobot.eventbus.Subscribe <methods>; }

    表示保留所有類中的有@org.greenrobot.eventbus.Subscribe注解的方法。<methods>是指方法,如果要保留字段,則使用<fields>。

    反正就是找不到類或成員,你就keep住。這里的keep規(guī)則也是很靈活的,比如除了上面指定的類,你也可以指定為接口:

    -keepclassmembernames,allowobfuscation interface * {@retrofit2.http.* <methods>; }

    可以指定繼承自某個(gè)類的所有類,如:

    -keep public class * extends android.app.Service

    可以指定實(shí)現(xiàn)某個(gè)接口的類,如:

    -keep class * implements com.google.gson.TypeAdapterFactory

    可以指定某個(gè)包下的所有類(包括子包)及所有成員,如:

    -keep class com.tencent.stat.** {* ;}

    除此之外,我們還可能會(huì)遇到其他問題,這里把其他常用的規(guī)則也快速過(guò)一下:

    注解解析不到?

    -keepattributes *Annotation*

    泛型轉(zhuǎn)換失敗?

    -keepattributes Signature

    枚舉?

    -keepclassmembers enum * { *; }

    掌握以上幾條規(guī)則,通常可以解決絕大多數(shù)混淆以后運(yùn)行出錯(cuò)的問題了。

    本篇講到這里,希望對(duì)被以上常見問題所困擾的同學(xué)有所幫助。這里需要注意一下,對(duì)于第一類問題,在編譯的時(shí)候就能暴露出來(lái),而第二類問題,只有在運(yùn)行到相關(guān)代碼時(shí)才會(huì)出現(xiàn)。所以如果一個(gè)項(xiàng)目以前是不使用混淆的話,在啟用混淆之后一定要做好回歸測(cè)試。

    總結(jié)

    以上是生活随笔為你收集整理的ProGuard常见问题及解决套路的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。