Proguard:如何避免缩小(和混淆)整个包以避免删除(和混淆)“未使用的方法”?

Posted

技术标签:

【中文标题】Proguard:如何避免缩小(和混淆)整个包以避免删除(和混淆)“未使用的方法”?【英文标题】:Proguard: How to avoid shrinking (and obfuscating) an entire package to avoid removing (and obfuscating) "unused methods"? 【发布时间】:2016-07-21 15:58:07 【问题描述】:

我目前正在使用一个使用大量反射的 android 库。

只要我启用 proguard 并运行它...它就会崩溃。

为什么?它使用了大量的反射,并且这些方法仅通过反射调用,因此它们被 proguard 检测为未使用并在收缩过程中被删除,因此抛出了 NoSuchMethodError

为什么会这样?这很容易弄清楚它们在收缩过程中被删除,因为 proguard 认为它们未被使用,因此删除了那段代码(所有方法)

那么,如何配置 proguard 以避免缩小或混淆整个包? (图书馆)

注意:我不想使用 -dontshrink 选项,因为它是全有或全无,我只想避免使用特定的包。


更多信息:

运行时错误如下:

E/AndroidRuntime: FATAL EXCEPTION: main Process: com.my.app.debug, PID: 3771 
java.lang.NoSuchMethodError: observeValueForKeyPath [class java.lang.String, class java.lang.Object, class com.my.lib.util.Dictionary, class java.lang.Object]
at com.my.lib.util.Observable$ObservationManager$Observer.<init>(SourceFile:47)
at com.my.lib.util.Observable$ObservationManager$Observer.<init>(SourceFile:26)
at com.my.lib.util.Observable$ObservationManager.addObserver(SourceFile:159)
...

请注意,问题在于内部内部类...

我目前的配置是这样的:

-keep,includedescriptorclasses class com.my.**  *; 
-keepclassmembers class com.my.lib**  *; 
-keep,includedescriptorclasses class com.my.lib.util.Observable$*  *; 
-keep,includedescriptorclasses class com.my.lib.util.Observable$*$*  *; 

但这显然只能避免混淆收缩过程中未删除的方法... 我需要避免在收缩过程中删除方法

【问题讨论】:

How to keep/exclude a particular package path when using proguard?的可能重复 不是重复的。我正在专门寻找一种方法来禁用其他答案无法解决的收缩(以及其他答案确实回答的混淆)。 为什么全局-dontshrink 这么可怕。你需要你的应用程序缩小。萎缩是否值得它目前给你带来的痛苦? 为什么我应该仅仅因为一个库使用反射就停止缩小我的应用程序?我可以,但这只是简单的方法。 【参考方案1】:

根据documentation -keep 即使在缩小时也应该可以工作,而-keepclassmembers 仅在“如果 [the] 类也被保留的情况下”才有效。

【讨论】:

其实你是对的。我做错了什么。【参考方案2】:
-keep class com.library.**  *;  

【讨论】:

这不起作用,因为收缩会删除未使用的方法。所以它只会保持那些被检测为已使用的未混淆的方法。在编译时未检测到反射.. 真的,你的问题没有提到反射使用的特殊性。但是,是的,你是对的, 添加了更多信息以帮助解答。 如果选择的正确答案与我所做的相同,那么我的答案怎么错了? 不是。但是正确的答案和你的不一样。【参考方案3】:

为了以后遇到类似问题的人,我会解释一下到底发生了什么:

    -keep class my.app.package 确实避免通过缩小和混淆来删除方法(@F43nd1r 的回答让我意识到,通过真正指出文档说它也避免缩小),所以问题出在其他地方

    在对 lib 的代码进行反编译并花一些时间阅读之后,我发现它作为参数接收到另一个类(不是来自该 lib)的实例和带有用于反射的方法名称的字符串。这就是问题所在,我还需要避免混淆该类。

【讨论】:

【参考方案4】:

我使用选项-dontshrink 来防止收缩。 来源:link

【讨论】:

以上是关于Proguard:如何避免缩小(和混淆)整个包以避免删除(和混淆)“未使用的方法”?的主要内容,如果未能解决你的问题,请参考以下文章

如何阻止proguard混淆整个包?

为 Proguard 指定类名以避免混淆

Android Proguard - dontobfuscate 不会禁用混淆

使用 ProGuard 时是不是可以混淆 GSON 注释中的字符串?

使用 proguard 的 Android 混淆应用程序会不断混淆库 jar - 是吗?

如何配置 ProGuard 以尊重 Jackson 模型?