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:找不到引用的类(到 R.java)

ADT R22 - Proguard - 找不到引用的类

Proguard 导致 100 个“找不到引用的类”警告,忽略 springframework 和 jackson 的保留规则

Proguard 警告:找不到引用的类 scala。*

Android ant 构建:proguard 在 ViewConfigurationCompatFroyo 类中找不到引用的方法

如何修复类 java.lang.Object 的现有方法“clone”和“finalize”的 proguard 警告“找不到引用的方法”