10

My app is crashing on pre-21 with java.lang.NoClassDefFoundError app.module.SomeClass error.

I already have Multidex enabled:

build.gradle:

android {
    defaultConfig {
        ...
        multiDexEnabled true
    }
}

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

My Application class:

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

After reading about Declaring classes required in the primary DEX file I created multidex-config.pro file to include app.module.** in primary DEX file:

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

And registered it in build.gradle:

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

I confirmed it by checking build/intermediates/legacy_multidex_main_dex_list/debug/mainDexList.txt and analyzing the debug apk (checking whether classes.dex includes app.module.SomeClass).

But I'm still getting java.lang.NoClassDefFoundError app.module.SomeClass error.

I also tried cleaning caches, running on different machines (cli build only without Android Studio), disabling instant run, specifying javaMaxHeapSize, just extending MultiDexApplication and etc.

What can I try next?

alashow
  • 2,735
  • 3
  • 21
  • 47

6 Answers6

8

We had a deeper look at this here:

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

There is an unfortunate bug in some Dalvik VMs on pre-21 devices where package private methods were sometimes incorrectly overriden by public methods in another package. If the package private method is final, that will then lead to errors of the form:

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

It looks like that could be what is hitting you here. Unfortunately, the only workaround for that particular issue is to rename your "clear" method to something else so that you do not hit this unfortunate VM bug.

Mads Ager
  • 134
  • 1
  • 2
4

Try below steps hope it will help you

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

Config your source Declare MultiDexApplication class in AndroidManifest.xml file

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

If we can’t extend MultiDexApplication we can install multiple dex files manually by overriding attachBaseContext(Context base) method in our Application class

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

Config dexOptions in app/build.gradle

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

Enable multidex in app/build.gradle

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' 
}

Disabled pre-dexing each module at the end of root build.gradle

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
        }
    }
}

Increase gradle jvm build in gradle.properties

org.gradle.jvmargs=-Xmx4608M
Hitesh Singh
  • 1,951
  • 1
  • 10
  • 15
1

In your app gradle file add this

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

javaMaxHeapSize

Specify the maximum size, in bytes, of the memory allocation pool. This value must a multiple of 1024 greater than 2MB. Append the letter k or K to indicate kilobytes, or m or M to indicate megabytes. The default value is chosen at runtime based on system configuration.

Ferran
  • 1,442
  • 1
  • 6
  • 10
1

try changing the order of instructions for DaggerApplication:

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

because the documentation reads:

Caution: Do not execute MultiDex.install() or any other code through reflection or JNI before MultiDex.install() is complete. Multidex tracing will not follow those calls, causing ClassNotFoundException or verify errors due to a bad class partition between DEX files.

Martin Zeitler
  • 1
  • 19
  • 155
  • 216
  • Moving `Multidex.install()` there cause actual multidex issues with other classes. I tried removing everything from my app class and just extending from `MultiDexApplication` – alashow Apr 28 '19 at 18:18
  • @alashow when it only crashes < API 21, this hints for the library not properly installed... because later the library is not required anymore. `DaggerApplication` might behave differently than `Application`. ` – Martin Zeitler May 01 '19 at 14:48
1

Try this

dexOptions {
            preDexLibraries = false
        }
jonatas Borges
  • 1,947
  • 13
  • 17
1

I use to have this issue when making ADB builds for ice cream sandwich (API 14) devices.

What worked for me was disabling Android Studio's instant run.

jhavatar
  • 3,236
  • 1
  • 18
  • 11