【问题标题】:multidex - NoClassDefFoundError with multidex enabledmultidex - 启用了 multidex 的 NoClassDefFoundError
【发布时间】:2019-04-23 01:44:48
【问题描述】:

我的应用在 pre-21 崩溃,出现 java.lang.NoClassDefFoundError app.module.SomeClass 错误。

我已经启用了 Multidex:

build.gradle:

android {
    defaultConfig {
        ...
        multiDexEnabled true
    }
}

dependencies {
   ...
   implementation "androidx.multidex:multidex:2.0.1"
}

我的应用程序类:

class App : DaggerApplication() {
    ...
    override fun attachBaseContext(base: Context) {
        super.attachBaseContext(base)
        MultiDex.install(this)
    }

在阅读了Declaring classes required in the primary DEX file 之后,我创建了multidex-config.pro 文件以将app.module.** 包含在主DEX 文件中:

-keep class app.module.** { *; }

并在 build.gradle 中注册:

android {
  buildTypes {
    debug {
      ...
      multiDexKeepProguard file('multidex-config.pro')
    }
}

我通过检查build/intermediates/legacy_multidex_main_dex_list/debug/mainDexList.txt 并分析调试apk 确认了这一点(检查classes.dex 是否包含app.module.SomeClass)。

但我仍然收到java.lang.NoClassDefFoundError app.module.SomeClass 错误。

我还尝试清理缓存,在不同的机器上运行(cli build 仅没有 Android Studio),禁用即时运行,指定 javaMaxHeapSize,只是扩展 MultiDexApplication 等等。

接下来我可以尝试什么?

【问题讨论】:

  • 使用这个 -keep public class app.module.** { *; }
  • @MahabubKarim 我试过了,没有效果。
  • 为什么multiDexKeepProguard file('multidex-config.pro') 在调试配置中?
  • @ArchieG.Quiñones,因为该应用在调试和发布版本中都崩溃了。
  • 如果我错了,请纠正我,但是您检查在 multidex 之后是否存在 app.module.SomeClass 并且它在那里?这听起来不像一个produard问题。您是否尝试过删除 proguard 优化?

标签: android kotlin android-multidex


【解决方案1】:

我们在这里进行了更深入的研究:

https://issuetracker.google.com/issues/131100011

在 21 之前的设备上的某些 Dalvik VM 中存在一个不幸的错误,其中包私有方法有时会被另一个包中的公共方法错误地覆盖。如果包私有方法是最终的,那将导致以下形式的错误:

E/dalvikvm: Method Lcom/mycompany/MyViewModel;.clear overrides final Landroidx/lifecycle/ViewModel;.clear

看起来这可能就是在这里击中你的原因。不幸的是,该特定问题的唯一解决方法是将您的“清除”方法重命名为其他名称,这样您就不会遇到这个不幸的 VM 错误。

【讨论】:

  • 谢谢你,这真的很有帮助。
【解决方案2】:

试试下面的步骤,希望对你有帮助

dependencies { 
 compile 'com.android.support:multidex:1.0.1' 
}

配置您的来源 在 AndroidManifest.xml 文件中声明 MultiDexApplication 类

<application
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme"
    android:name="android.support.multidex.MultiDexApplication">
</application>

如果我们不能扩展 MultiDexApplication,我们可以通过覆盖 Application 类中的 attachBaseContext(Context base) 方法来手动安装多个 dex 文件

public class HelloMultiDexApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
    }
@Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        MultiDex.install(this);
    }
}

在 app/build.gradle 中配置 dexOptions

android {
    dexOptions {
        incremental true         
        javaMaxHeapSize "4g"
    }
}

在 app/build.gradle 中启用 multidex

android {
 defaultConfig { 
  multiDexEnabled true 
 }
}
afterEvaluate {
    tasks.matching {
        it.name.startsWith('dex')
    }.each { dx ->
        if (dx.additionalParameters == null) {
            dx.additionalParameters = ['--multi-dex']
        } else {
            dx.additionalParameters += '--multi-dex'
        }
    }
}
dependencies {
 compile 'com.android.support:multidex:1.0.1' 
}

在根 build.gradle 的末尾禁用 pre-dexing 每个模块

subprojects {
    project.plugins.whenPluginAdded { plugin ->
        if ("com.android.build.gradle.AppPlugin".equals(plugin.class.name)) {
            project.android.dexOptions.preDexLibraries = false
        } else if ("com.android.build.gradle.LibraryPlugin".equals(plugin.class.name)) {
            project.android.dexOptions.preDexLibraries = false
        }
    }
}

在 gradle.properties 中增加 gradle jvm build

org.gradle.jvmargs=-Xmx4608M

【讨论】:

    【解决方案3】:

    在你的应用 gradle 文件中添加这个

    android {
        ...
        dexOptions {
            jumboMode = true
            javaMaxHeapSize "4g"
         }
         defaultConfig {
             ...
    

    javaMaxHeapSize

    指定内存分配池的最大大小(以字节为单位)。此值必须是大于 2MB 的 1024 的倍数。附加字母 k 或 K 表示千字节,或附加字母 m 或 M 表示兆字节。默认值是在运行时根据系统配置选择的。

    【讨论】:

      【解决方案4】:

      尝试更改DaggerApplication 的指令顺序:

      override fun onCreate() {
          MultiDex.install(this)
          super.onCreate()
      }
      

      因为documentation 写着:

      注意:在MultiDex.install() 完成之前,不要通过反射或JNI 执行MultiDex.install() 或任何其他代码。 Multidex 跟踪不会跟踪这些调用,导致 ClassNotFoundException 或验证错误,因为 DEX 文件之间的类分区错误。

      【讨论】:

      • Multidex.install() 移动到那里会导致其他类出现实际的多索引问题。我尝试从我的应用程序类中删除所有内容,并仅从 MultiDexApplication 扩展
      • @alashow 当它仅崩溃时 DaggerApplication 的行为可能与 Application 不同。 Manifest.xml 中的 &lt;application android:name 可能会丢失;这个普通定义了Application入口点。
      【解决方案5】:

      试试这个

      dexOptions {
                  preDexLibraries = false
              }
      

      【讨论】:

        【解决方案6】:

        在为冰淇淋三明治 (API 14) 设备制作 ADB 版本时,我曾经遇到过这个问题。

        对我有用的是disabling Android Studio's instant run

        【讨论】:

          猜你喜欢
          • 2014-12-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多