gpt4 book ai didi

android - Proguard 剥离了实现接口(interface)。运行时引发 java.lang.IncompleteClassChangeError

转载 作者:行者123 更新时间:2023-12-02 12:17:09 29 4
gpt4 key购买 nike

将依赖项更新到最新版本后,由于缺少接口(interface)实现,我们在发布版本中遇到了运行时崩溃

java.lang.IncompatibleClassChangeError: 
Class 'com.mypackage.app.data.cache.query.user.QueryUserFollowersCountById'
does not implement interface 'com.mypackage.app.data.cache.query.Query'
in call to 'java.lang.String[] com.mypackage.app.data.cache.query.Query.c()'
(declaration of 'com.mypackage.app.data.cache.database.util.Db'
appears in /data/app/com.mypackage.app-2/base.apk:classes2.dex)

经过两天的调试,我们认为该问题与 Proguard 在收缩阶段删除“implements Query”有关。接口(interface)本身保留了数百个其他类中使用的原样,仅在 3 个类中缺失。我们还发现一些 RxJava Func0 和 Action0 接口(interface)以同样的方式被剥离,同样是在极少数地方。因此,该应用程序可以在 95% 的屏幕上完美运行,但在缺少界面实现的地方显然会崩溃。

  1. 我们正在使用 Gradle 构建工具版本 3.1.3,但也尝试过使用 3.3.0-alpha03,还尝试禁用 D8,因此它不应该是构建工具问题(Proguard 版本 5.3.3 和 6.0.3 的行为也是如此)在这种情况下以同样的方式)
  2. 当 Dagger2 从 2.11 版本升级到 2.12 或更高版本时,会出现此问题,因此可能与应用中的字段/方法/类等数量有关
  3. 即使使用 -dontoptimize,问题仍然存在,我们已阅读 Proguard 文档并启用/禁用了几乎所有相关标志
  4. 通过将 minifyEnabled 设置为 false 或使用 Proguard 的 -dontshrink 标志即可解决该问题
  5. 该应用使用 Multidex,均使用 Dagger 2.11 和 Dagger 2.12 构建,最终生成 3 个classes.dex 文件。在这两种情况下,有问题的接口(interface)和实现都位于同一个 .dex 文件中。
  6. 例如,同一个包中有 5 个文件实现 Query,其中 3 个文件在生成的字节码中具有接口(interface),但 2 个文件没有。所以应该与文件放置位置无关。

使用 Dagger 2.11 或 -dontshrink 构建时的字节码

.class public Lcom/mypackage/app/data/cache/query/user/QueryUserFollowersCountById;
.super Ljava/lang/Object;
.source "SourceFile"

# interfaces
.implements Lcom/mypackage/app/data/cache/query/Query;

# annotations
.annotation system Ldalvik/annotation/Signature;
value = {
"Ljava/lang/Object;",
"Lcom/mypackage/app/data/cache/query/Query<",
"Ljava/lang/Integer;",
">;"
}
.end annotation
......

使用 Dagger 2.12 或更高版本构建时的字节码

.class public Lcom/mypackage/app/data/cache/query/user/QueryUserFollowersCountById;
.super Ljava/lang/Object;
.source "SourceFile"

# annotations
.annotation system Ldalvik/annotation/Signature;
value = {
"Ljava/lang/Object;"
}
.end annotation
......

我们显然希望使用最新版本的 Dagger2,并使用 Proguard 不断缩小和优化我们的代码。

  1. 如何确保 Proguard 不会删除实现接口(interface)语句?
  2. 或者如何向 Proguard 收缩步骤添加日志记录/调试?

最佳答案

如果 proguard 正在删除实现部分,则在优化阶段 proguard 更有可能将其视为死代码。

你已经提到了

The issue is gone by setting minifyEnabled to false or by using -dontshrink flag for Proguard

这验证了我的假设,即实现部分可能是死代码

请仔细阅读此thread ,这解释了如何获取死代码列表。换句话说,关于使用 -printusage [文件名] 添加日志进行调试的查询的答案

关于android - Proguard 剥离了实现接口(interface)。运行时引发 java.lang.IncompleteClassChangeError,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51381497/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com