Proguard 和 Kotlin 的“找不到引用的类”
Posted
技术标签:
【中文标题】Proguard 和 Kotlin 的“找不到引用的类”【英文标题】:"can't find referenced class" with Proguard and Kotlin 【发布时间】:2016-09-22 17:13:25 【问题描述】:我在使用 proguard 和 kotlin 时遇到了一个奇怪的问题。我正在逐渐将一个 proguarded 项目转换为 kotlin - 到目前为止效果很好,但是在转换某些类时我遇到了 proguard 错误。我还不能分离出这些类的特殊属性是什么,所以它坏了——它们似乎与其他类没有什么不同。例如 InputStreamWithSource 只是:
package org.ligi.passandroid.model
import java.io.InputStream
class InputStreamWithSource(val source: String, val inputStream: InputStream)
它完全可以在 IDE 中运行——我可以部署到设备上——而且所有 UI 测试都运行良好。就在尝试 assembleRelease 项目时,我遇到了我不明白的 proguard 错误:
Warning: org.ligi.passandroid.ui.FileUnzipControllerSpec: can't find referenced class org.ligi.passandroid.model.InputStreamWithSource
Warning: org.ligi.passandroid.ui.FileUnzipControllerSpec: can't find referenced class org.ligi.passandroid.model.InputStreamWithSource
Warning: org.ligi.passandroid.ui.InputStreamProvider: can't find referenced class org.ligi.passandroid.model.InputStreamWithSource
Warning: org.ligi.passandroid.ui.InputStreamProvider: can't find referenced class org.ligi.passandroid.model.InputStreamWithSource
Warning: org.ligi.passandroid.ui.InputStreamProvider: can't find referenced class org.ligi.passandroid.model.InputStreamWithSource
Warning: org.ligi.passandroid.ui.InputStreamProvider: can't find referenced class org.ligi.passandroid.model.InputStreamWithSource
Warning: org.ligi.passandroid.ui.InputStreamProvider: can't find referenced class org.ligi.passandroid.model.InputStreamWithSource
Warning: org.ligi.passandroid.ui.InputStreamProvider: can't find referenced class org.ligi.passandroid.model.InputStreamWithSource
Warning: org.ligi.passandroid.ui.PassImportActivity$ImportAndShowAsyncTask: can't find referenced class org.ligi.passandroid.model.InputStreamWithSource
Warning: org.ligi.passandroid.ui.PassImportActivity$ImportAndShowAsyncTask: can't find referenced class org.ligi.passandroid.model.InputStreamWithSource
Warning: org.ligi.passandroid.ui.PassImportActivity$ImportAndShowAsyncTask: can't find referenced class org.ligi.passandroid.model.InputStreamWithSource
Warning: org.ligi.passandroid.ui.PassImportActivity$ImportAndShowAsyncTask: can't find referenced class org.ligi.passandroid.model.InputStreamWithSource
Warning: org.ligi.passandroid.ui.PassImportActivity$ImportAndShowAsyncTask: can't find referenced class org.ligi.passandroid.model.InputStreamWithSource
Warning: org.ligi.passandroid.ui.PassViewActivityBase$UpdateAsync: can't find referenced class org.ligi.passandroid.model.InputStreamWithSource
Warning: org.ligi.passandroid.ui.PassViewActivityBase$UpdateAsync: can't find referenced class org.ligi.passandroid.model.InputStreamWithSource
Warning: org.ligi.passandroid.ui.PassViewActivityBase$UpdateAsync: can't find referenced class org.ligi.passandroid.model.InputStreamWithSource
Warning: org.ligi.passandroid.ui.SearchPassesIntentService: can't find referenced class org.ligi.passandroid.model.InputStreamWithSource
Warning: org.ligi.passandroid.ui.UnzipPassController: can't find referenced class org.ligi.passandroid.model.InputStreamWithSource
Warning: org.ligi.passandroid.ui.UnzipPassController: can't find referenced class org.ligi.passandroid.model.InputStreamWithSource
Warning: org.ligi.passandroid.ui.UnzipPassController$InputStreamUnzipControllerSpec: can't find referenced class org.ligi.passandroid.model.InputStreamWithSource
Warning: org.ligi.passandroid.ui.UnzipPassController$InputStreamUnzipControllerSpec: can't find referenced class org.ligi.passandroid.model.InputStreamWithSource
Warning: org.ligi.passandroid.ui.UnzipPassController$InputStreamUnzipControllerSpec: can't find referenced class org.ligi.passandroid.model.InputStreamWithSource
Warning: org.ligi.passandroid.ui.UnzipPassController$InputStreamUnzipControllerSpec: can't find referenced class org.ligi.passandroid.model.InputStreamWithSource
Warning: org.ligi.passandroid.ui.UnzipPassDialog: can't find referenced class org.ligi.passandroid.model.InputStreamWithSource
Warning: org.ligi.passandroid.ui.UnzipPassDialog: can't find referenced class org.ligi.passandroid.model.InputStreamWithSource
Warning: org.ligi.passandroid.ui.UnzipPassDialog$1AlertDialogUpdater: can't find referenced class org.ligi.passandroid.model.InputStreamWithSource
Warning: org.ligi.passandroid.ui.UnzipPassDialog$1AlertDialogUpdater: can't find referenced class org.ligi.passandroid.model.InputStreamWithSource
当我在 proguard 配置中为这些类添加 dontwarn 时,它会在运行时崩溃 - 所以这些类确实被删除了 - 但它们不应该在使用时被删除。
我可以通过在 proguard-config 中为这些类添加 keep class/enum 来解决这个问题 - 但问题是为什么这些类需要这样做 - 恕我直言,它不应该是必需的
任何人都有一些想法可能导致此问题或如何最好地调查此问题?完整来源在这里:https://github.com/ligi/PassAndroid
【问题讨论】:
【参考方案1】:我会确保我在 proguard 中定义了自己的包 - 如下所示:
-dontwarn org.ligi.passandroid.**
-keep class org.ligi.passandroid.** *;
【讨论】:
如果你这样做了,那么运行 proguard 就没有意义了 @GregEnnis 为你自己的代码,这很好,因为任何未使用的代码都应该从项目中删除。 3rd 方代码是另一回事。 @GregEnnis 是对的。如果您不仅想使用 proguard 进行优化(您可能指的是什么),而且还想进行混淆,那么您不应该这样做,因为它会使您自己的所有代码保持原样,任何人都可以清楚地阅读您的APK。 @ubuntudroid-keep
表示您将类保留在包下并且没有让 proguard 删除它们。 Specifies classes and class members (fields and methods) to be preserved as entry points to your code.
guardsquare.com/en/products/proguard/manual/usage 与混淆您的代码无关。混淆选项guardsquare.com/en/products/proguard/manual/…
@RayHunter 我的立场是正确的——我的错。感谢您的参考! :)以上是关于Proguard 和 Kotlin 的“找不到引用的类”的主要内容,如果未能解决你的问题,请参考以下文章
Proguard 导致 100 个“找不到引用的类”警告,忽略 springframework 和 jackson 的保留规则
Android ant 构建:proguard 在 ViewConfigurationCompatFroyo 类中找不到引用的方法
如何修复类 java.lang.Object 的现有方法“clone”和“finalize”的 proguard 警告“找不到引用的方法”