Andrzej Zabost
Andrzej Zabost

Reputation: 1521

ClassNotFoundException in Android project only on my PC

Recently, when I was going to finish my work at home on my PC with Windows 8.1, I've found out the project doesn't work properly - it compiles, runs on the emulator and crashes at some specific point (it's 100% reproducible on my PC).

However, the same repository revision works on a Mac at work and on my colleagues Windows 10 machine.

Every mentioned environment was using Android Studio 2.3.1, gradle 3.3 and Kotlin 1.1.1 and running the application on the API 25 x86_64 image.

The project is using multidex 1.0.1 library.

The crash happens due to the following exception:

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.project.app, PID: 2533
    java.lang.NoClassDefFoundError: Failed resolution of: Lcom/project/package/SomeActivityKt$sam$Action1$22181393;
        at com.project.package.SomeActivity.getDataFor(SomeActivity.kt:164)
        at com.project.package.SomeActivity.getData(SomeActivity.kt:147)
        at com.project.package.SomeActivity.onResume(SomeActivity.kt:142)
        at android.app.Instrumentatcomn.callActivityOnResume(Instrumentatcomn.java:1269)
        at android.app.Activity.performResume(Activity.java:6783)
        at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3406)
        at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3469)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2732)
        at android.app.ActivityThread.-wrap12(ActivityThread.java)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1477)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:154)
        at android.app.ActivityThread.main(ActivityThread.java:6119)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
     Caused by: java.lang.ClassNotFoundException: Didn't find class "com.project.package.SomeActivityKt$sam$Action1$22181393" on path: DexPathList[[zip file "/data/app/com.project.app-1/base.apk", zip file "/data/app/com.project.app-1/split_lib_dependencies_apk.apk", zip file "/data/app/com.project.app-1/split_lib_slice_0_apk.apk", zip file "/data/app/com.project.app-1/split_lib_slice_1_apk.apk", zip file "/data/app/com.project.app-1/split_lib_slice_2_apk.apk", zip file "/data/app/com.project.app-1/split_lib_slice_3_apk.apk", zip file "/data/app/com.project.app-1/split_lib_slice_4_apk.apk", zip file "/data/app/com.project.app-1/split_lib_slice_5_apk.apk", zip file "/data/app/com.project.app-1/split_lib_slice_6_apk.apk", zip file "/data/app/com.project.app-1/split_lib_slice_7_apk.apk", zip file "/data/app/com.project.app-1/split_lib_slice_8_apk.apk", zip file "/data/app/com.project.app-1/split_lib_slice_9_apk.apk"],nativeLibraryDirectories=[/data/app/com.project.app-1/lib/x86_64, /data/app/com.project.app-1/base.apk!/lib/x86_64, /data/app/com.project.app-1/split_lib_dependencies_apk.apk!/lib/x86_64, /data/app/com.project.app-1/split_lib_slice_0_apk.apk!/lib/x86_64, /data/app/com.project.app-1/split_lib_slice_1_apk.apk!/lib/x86_64, /data/app/com.project.app-1/split_lib_slice_2_apk.apk!/lib/x86_64, /data/app/com.project.app-1/split_lib_slice_3_apk.apk!/lib/x86_64, /data/app/com.project.app-1/split_lib_slice_4_apk.apk!/lib/x86_64, /data/app/com.project.app-1/split_lib_slice_5_apk.apk!/lib/x86_64, /data/app/com.project.app-1/split_lib_slice_6_apk.apk!/lib/x86_64, /data/app/com.project.app-1/split_lib_slice_7_apk.apk!/lib/x86_64, /data/app/com.project.app-1/split_lib_slice_8_apk.apk!/lib/x86_64, /data/app/com.project.app-1/split_lib_slice_9_apk.apk!/lib/x86_64, /system/lib64, /vendor/lib64]]
        at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:380)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
        at com.project.package.SomeActivity.getDataFor(SomeActivity.kt:164) 
        at com.project.package.SomeActivity.getData(SomeActivity.kt:147) 
        at com.project.package.SomeActivity.onResume(SomeActivity.kt:142) 
        at android.app.Instrumentatcomn.callActivityOnResume(Instrumentatcomn.java:1269) 
        at android.app.Activity.performResume(Activity.java:6783) 
        at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3406) 
        at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3469) 
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2732) 
        at android.app.ActivityThread.-wrap12(ActivityThread.java) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1477) 
        at android.os.Handler.dispatchMessage(Handler.java:102) 
        at android.os.Looper.loop(Looper.java:154) 
        at android.app.ActivityThread.main(ActivityThread.java:6119) 

BaseActivity.kt

abstract class BaseActivity : RxAppCompatActivity(), HasErrorHandler (...)

SomeActivity.kt - this crashes

class SomeActivity : BaseActivity(), HasFullWindowProgress (...) {

    (...)

    private fun getDataFor(id: String) {

        apiClient.somethingList(id)
                .map { response -> response.toSomethingList() }
                .lifecycle(this)
                .showProgress(this)
                .observeOnMainThread() // <== line 164
                .subscribe({
                    LOG.info("Something list fetched ${it.size}")
                    adapter.setItems(it)

                }, defaultOnError("Fetching something list failed"))
    }
}

AnotherActivity.kt - uses the same functions as SomeActivity and does not crash

class AnotherActivity : BaseActivity(), HasFullWindowProgress (...) {

    (...)

    private fun getData() {
        somethingElse.user?.id?.let { id ->

            apiClient.somethingElseList()
                    .map { response -> response.toAnotherList(id) }
                    .lifecycle(this)
                    .showProgress(this)
                    .observeOnMainThread()
                    .subscribe({
                        onNewSomethingElseList(id, it)
                    }, defaultOnError("Fetching somethingElseList for somethingElse failed"))
        }

    }
}

ActivityErrorHandlingExtensions.kt

fun <T> T.defaultOnError(message: String, vararg args: Any?): (Throwable) -> Unit where T : HasErrorHandler, T : Activity {
    val targetClass = javaClass
    val activity = this
    return { err ->
        val messageFormats = (args.toList() + err).toTypedArray()
        LoggerFactory.getLogger(targetClass).error(message, *messageFormats)
        errorHandler.default(err, activity)
    }
}

ObservableExtensions.kt

fun <T> Observable<T>.lifecycle(activity: RxAppCompatActivity) : Observable<T> {
    return compose(activity.bindToLifecycle<T>())
}

fun <T> Observable<T>.observeOnMainThread() : Observable<T> {
    return observeOn(AndroidSchedulers.mainThread())
}

Progress.kt

fun <T> Observable<T>.showProgress(hasProgress: HasFullWindowProgress): Observable<T> {
    return compose {
        it.doOnSubscribe {
            MAIN_THREAD_WORKER.schedule {
                hasProgress.fullWindowProgress.visibility = View.VISIBLE
            }
        }.doAfterTerminate {
            MAIN_THREAD_WORKER.schedule {
                hasProgress.fullWindowProgress.visibility = View.GONE
            }
        }
    }
}

All this code was in the project for over a month or two and it was working on my PC two weeks ago.

What I have already tried:

Any ideas what's wrong here?


Kotlin bytecode of the getDataFor method:

  private final getDataFor(Ljava/lang/String;)V
   L0
    LINENUMBER 160 L0
   L1
    LINENUMBER 165 L1
   L2
    LINENUMBER 160 L2
   L3
    LINENUMBER 164 L3
   L4
    LINENUMBER 160 L4
   L5
    LINENUMBER 163 L5
   L6
    LINENUMBER 160 L6
   L7
    LINENUMBER 162 L7
   L8
    LINENUMBER 160 L8
   L9
    LINENUMBER 161 L9
   L10
    LINENUMBER 160 L10
    ALOAD 0
    GETFIELD com/project/package/SomeActivity.apiClient : Lcom/project/network/ApiClient;
    DUP
    IFNONNULL L11
    LDC "apiClient"
    INVOKESTATIC kotlin/jvm/internal/Intrinsics.throwUninitializedPropertyAccessException (Ljava/lang/String;)V
   L11
    ALOAD 1
    INVOKEVIRTUAL com/project/network/ApiClient.somethingList (Ljava/lang/String;)Lrx/Observable;
    GETSTATIC com/project/package/SomeActivity$getDataFor$1.INSTANCE : Lcom/project/package/SomeActivity$getDataFor$1;
    CHECKCAST rx/functions/Func1
   L12
    LINENUMBER 161 L12
    INVOKEVIRTUAL rx/Observable.map (Lrx/functions/Func1;)Lrx/Observable;
    ALOAD 0
    CHECKCAST com/trello/rxlifecycle/components/support/RxAppCompatActivity
   L13
    LINENUMBER 162 L13
    INVOKESTATIC com/project/extensions/ObservableExtensionsKt.lifecycle (Lrx/Observable;Lcom/trello/rxlifecycle/components/support/RxAppCompatActivity;)Lrx/Observable;
    ALOAD 0
    CHECKCAST com/project/widgets/HasFullWindowProgress
   L14
    LINENUMBER 163 L14
    INVOKESTATIC com/project/widgets/ProgressKt.showProgress (Lrx/Observable;Lcom/project/widgets/HasFullWindowProgress;)Lrx/Observable;
   L15
    LINENUMBER 164 L15
    INVOKESTATIC com/project/extensions/ObservableExtensionsKt.observeOnMainThread (Lrx/Observable;)Lrx/Observable;
    NEW com/project/package/SomeActivity$getDataFor$2
    DUP
    ALOAD 0
    INVOKESPECIAL com/project/package/SomeActivity$getDataFor$2.<init> (Lcom/project/package/SomeActivity;)V
    CHECKCAST rx/functions/Action1
    NEW com/project/package/SomeActivityKt$sam$Action1$22181393
    DUP
    ALOAD 0
    LDC "Fetching something list failed"
    ICONST_0
    ANEWARRAY java/lang/Object
    INVOKESTATIC com/project/extensions/ActivityErrorHandlingExtensionsKt.defaultOnError (Landroid/app/Activity;Ljava/lang/String;[Ljava/lang/Object;)Lkotlin/jvm/functions/Function1;
    DUP
    IFNONNULL L16
    POP
    POP2
    ACONST_NULL
    GOTO L17
   L16
    INVOKESPECIAL com/project/package/SomeActivityKt$sam$Action1$22181393.<init> (Lkotlin/jvm/functions/Function1;)V
   L17
    CHECKCAST rx/functions/Action1
   L18
    LINENUMBER 165 L18
    INVOKEVIRTUAL rx/Observable.subscribe (Lrx/functions/Action1;Lrx/functions/Action1;)Lrx/Subscription;
    POP
   L19
    LINENUMBER 170 L19
    RETURN
   L20
    LOCALVARIABLE this Lcom/project/package/SomeActivity; L0 L20 0
    LOCALVARIABLE id Ljava/lang/String; L0 L20 1
    MAXSTACK = 7
    MAXLOCALS = 2

Upvotes: 3

Views: 1104

Answers (1)

Alejandro Casanova
Alejandro Casanova

Reputation: 3681

I ran into a similar problem few weeks ago. Here is basically what I did to avoid the ClassNotFoundException, in my case was due to the Multidex "configuration" after updating Android Studio, gradle, etc.

  1. Add compile 'com.android.support:multidex:1.0.1'to the dependencies list in your app gradle file.
  2. Remove Multidex.install(this); from the onCreate() method of your Application class and add the following in your Application class:

    @Override
    protected void attachBaseContext(Context context) {
        super.attachBaseContext(context);
        MultiDex.install(this);
    }
    

I got the error after updating the gradle version, etc., so make sure you have everything up to date as well.

Hope it helps.

Upvotes: 1

Related Questions