Search code examples
androidandroid-studiojvmclassnotfoundexceptioninner-classes

ClassNotFoundException for InnerClass because Compiler generates classpath differently


I am currently developing an Android Library Module. But today we got a strange error from the jvm.

The exception stack is as follows

E/FeedbackRepository: 'this' aufgerufen
D/AndroidRuntime: Shutting down VM
E/AndroidRuntime: FATAL EXCEPTION: main
    Process: ch.fhnw.edu.fcp.feedbackcommprocess, PID: 26531
    java.lang.NoClassDefFoundError: Failed resolution of: Lch/fhnw/edu/fcp/postcard/persistence/FeedbackRepository$UpdateSentDatetimeAsyncTask;
        at ch.fhnw.edu.fcp.postcard.persistence.FeedbackRepository.sendFeedback(FeedbackRepository.java:165)
        at ch.fhnw.edu.fcp.postcard.viewmodel.FeedbackViewModel.send(FeedbackViewModel.java:137)
        at ch.fhnw.edu.fcp.postcard.activity.TextSideActivity.sendFeedback(TextSideActivity.java:312)
        at ch.fhnw.edu.fcp.postcard.activity.TextSideActivity$4.onClick(TextSideActivity.java:107)
        at android.view.View.performClick(View.java:7352)
        at android.widget.TextView.performClick(TextView.java:14177)
        at android.view.View.performClickInternal(View.java:7318)
        at android.view.View.access$3200(View.java:846)
        at android.view.View$PerformClick.run(View.java:27800)
        at android.os.Handler.handleCallback(Handler.java:873)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:214)
        at android.app.ActivityThread.main(ActivityThread.java:7050)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:965)
     Caused by: java.lang.ClassNotFoundException: Didn't find class "ch.fhnw.edu.fcp.postcard.persistence.FeedbackRepository$UpdateSentDatetimeAsyncTask" on path: DexPathList[[zip file "/data/app/ch.fhnw.edu.fcp.feedbackcommprocess-86NmPv8EIZeWCEcZkVIMKw==/base.apk"],nativeLibraryDirectories=[/data/app/ch.fhnw.edu.fcp.feedbackcommprocess-86NmPv8EIZeWCEcZkVIMKw==/lib/arm64, /system/lib64, /system/vendor/lib64]]
        at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:134)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:379)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
        at ch.fhnw.edu.fcp.postcard.persistence.FeedbackRepository.sendFeedback(FeedbackRepository.java:165) 
        at ch.fhnw.edu.fcp.postcard.viewmodel.FeedbackViewModel.send(FeedbackViewModel.java:137) 
        at ch.fhnw.edu.fcp.postcard.activity.TextSideActivity.sendFeedback(TextSideActivity.java:312) 
        at ch.fhnw.edu.fcp.postcard.activity.TextSideActivity$4.onClick(TextSideActivity.java:107) 
        at android.view.View.performClick(View.java:7352) 
        at android.widget.TextView.performClick(TextView.java:14177) 
        at android.view.View.performClickInternal(View.java:7318) 
        at android.view.View.access$3200(View.java:846) 
        at android.view.View$PerformClick.run(View.java:27800) 
        at android.os.Handler.handleCallback(Handler.java:873) 
        at android.os.Handler.dispatchMessage(Handler.java:99) 
        at android.os.Looper.loop(Looper.java:214) 
        at android.app.ActivityThread.main(ActivityThread.java:7050) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:965) 
I/Process: Sending signal. PID: 26531 SIG: 9
Process 26531 terminated.

The exception is thrown when we try to create a new UpdateSentDatetimeAsyncTask and the jvm seems to be unable to find the class.


// This is part of the FeedbackRepository class

public void sendFeedback(Feedback feedback) {
    Log.wtf("FeedbackRepsitory", "#sendFeedback called");
    new UpdateSentDatetimeAsyncTask(this.feedbackDAO).execute(feedback);

    // TODO: Networkservice.send(feedback)
}

// This is the InnerClass we want to instanciate
private static class UpdateSentDatetimeAsyncTask extends AsyncTask<Feedback, Void, Void> {

    private WeakReference<FeedbackDAO> mAsyncTaskDao;

    UpdateSentDatetimeAsyncTask(FeedbackDAO dao) { mAsyncTaskDao = new WeakReference<>(dao); }

    @Override
    protected Void doInBackground(final Feedback... params) {
        Feedback feedback = params[0];
        mAsyncTaskDao.get().updateSentDateTimeByUuid(new DateTime(), feedback.getUuid());
        return null;
    }
}

We have already checked the .jar package within the .aar package we use in our demo app. The class FeedbackRepository$UpdateSentDatetimeAsyncTask.class exists in the proper place.

We have decompiled the FeedbackRepository.class and looked at the instanciation of the class there. It becomes apparent that there seems to be an issue with the compilation I really dont know how to solve.

I have included a snippet where we pretty much do the exact same thing however the compiler generates something way different.

public void sendFeedback(Feedback feedback) {
    // Here the compiler references the class by the full package path
    // This is the only place where it does it so I am blaming this
    // code generated code peace
    (new ch.fhnw.edu.fcp.postcard.persistence.FeedbackRepository.UpdateSentDatetimeAsyncTask(this.feedbackDAO)).execute(new Feedback[]{feedback});
}

public void delete(Feedback feedback) {
    // The inner class is referenced differently here
    // This code part works fine. Class is found.
    (new FeedbackRepository.DeleteFeedbackAsyncTask(this.feedbackDAO)).execute(new Feedback[]{feedback});
}

Some more information what we already tried
- Deleteing all build artifacts and rebuild the whole solution
- Recreating the InnerClass implementation and see if the compiler compiles it correctly
- Deleteing the whole project and clone it from the repository. (Still error occurs)

When renaming the class it runs fine. Renaming it back to the desired class name however recreated the issue.
What else is there we can do? Are there specific caches we need to delete?

EDIT 1:
So we ran the build on a different machine. Here it works. But is there a proper way to fix the Android-Studio project?

EDIT 2:
Just deleted all .gradle/caches to no avail

EDIT 3:
Reinstalled Android Studio and deleted all configuration folders before reinstaling. Still we get the same error. This is really frustrating because such an error should be on a project to project bases. That this seems to become a systemwide issue is madness and should never happen.
We also excluded many build and cache folders from antivirus scans.

System and installation information:
- Windows 10
- Android Studio 3.5 Beta 5


Solution

  • Okay so it was pretty much our fault.

    Though the code analysis and and the compiler really did not make a beep about it either! Issue was we had the inner class with the same name twice! That is 'UpdateSentDatetimeAsyncTask'

    Its strange that nothing was complaining about it. Normally this kind of stuff is reported by the IDE or the Compiler. Well either way, its fixed now.