Android: Rare and Non-Reproducible ClassNotFoundException
Asked Answered
E

2

7

I have a published app that gets reports about a ClassNotFoundExceptionfrom users that I went beyond my wits end trying to fix. I have not been able to reproduce this crash and similar instances of this error here on SO have either been cases of incorrect path to a dependency or a different package in the MainActivity than the manifest.

The issues with the wrong path to the dependencies are an Eclipse thing, while all the other errors could be easily fixed with Android Studio's "sync" and "clean project" (which I did to no avail).

I've triple checked all the package names and did not find any discrepancies.

Here is my manifest:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.johan.fsc">

    <uses-permission android:name = "android.permission.VIBRATE"/>
    <uses-permission android:name="com.android.vending.BILLING" />
    <application
        android:allowBackup="true"
        android:icon="@drawable/logo"
        android:label="@string/app_name"
        android:fullBackupContent="true">
        <activity
            android:name="com.johan.fsc.MainActivity"
            android:screenOrientation="portrait"
            android:label="@string/app_name"
            android:theme="@style/splashscreenTheme"
            android:hardwareAccelerated="false"
            android:largeHeap="true">>
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>

                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <activity android:name = "com.johan.fsc.SettingsActivity"
            android:theme="@style/PreferencesTheme"/>
    </application>

Here is the error report I always get from users:

java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.johan.fsc/com.johan.fsc.MainActivity}: java.lang.ClassNotFoundException: Didn't find class "com.johan.fsc.MainActivity" on path: DexPathList[[zip file "/data/app/com.johan.fsc-1/base.apk"],nativeLibraryDirectories=[/vendor/lib, /system/lib]]
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2426)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2595)
    at android.app.ActivityThread.access$800(ActivityThread.java:178)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1470)
    at android.os.Handler.dispatchMessage(Handler.java:111)
    at android.os.Looper.loop(Looper.java:194)
    at android.app.ActivityThread.main(ActivityThread.java:5624)
    at java.lang.reflect.Method.invoke(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:372)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:959)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:754)
Caused by: java.lang.ClassNotFoundException: Didn't find class "com.johan.fsc.MainActivity" on path: DexPathList[[zip file "/data/app/com.johan.fsc-1/base.apk"],nativeLibraryDirectories=[/vendor/lib, /system/lib]]
    at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:511)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:469)
    at android.app.Instrumentation.newActivity(Instrumentation.java:1071)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2416)
    ... 10 more
    Suppressed: java.io.IOException: Failed to open oat file from dex location '/data/app/com.johan.fsc-1/base.apk'
        at dalvik.system.DexFile.openDexFileNative(Native Method)
        at dalvik.system.DexFile.openDexFile(DexFile.java:295)
        at dalvik.system.DexFile.<init>(DexFile.java:80)
        at dalvik.system.DexFile.<init>(DexFile.java:59)
        at dalvik.system.DexPathList.loadDexFile(DexPathList.java:262)
        at dalvik.system.DexPathList.makeDexElements(DexPathList.java:231)
        at dalvik.system.DexPathList.<init>(DexPathList.java:109)
        at dalvik.system.BaseDexClassLoader.<init>(BaseDexClassLoader.java:48)
        at dalvik.system.PathClassLoader.<init>(PathClassLoader.java:65)
        at android.app.ApplicationLoaders.getClassLoader(ApplicationLoaders.java:57)
        at android.app.LoadedApk.getClassLoader(LoadedApk.java:370)
        at android.app.LoadedApk.makeApplication(LoadedApk.java:562)
        at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4818)
        at android.app.ActivityThread.access$1500(ActivityThread.java:178)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1531)
        ... 7 more
Caused by: java.io.IOException: Failed to open oat file from /data/app/com.johan.fsc-1/arm/base.odex (error Failed to open oat filename for reading: No such file or directory) (no dalvik_cache availible) and relocation failed.
        ... 22 more
Caused by: java.io.IOException: 
        ... 22 more
Caused by: java.io.IOException: Failed to remove obsolete file from /data/dalvik-cache/arm/data@[email protected]@[email protected] when searching for dex file /data/app/com.johan.fsc-1/base.apk: Permission denied
        ... 22 more
    Suppressed: java.lang.ClassNotFoundException: com.johan.fsc.MainActivity
        at java.lang.Class.classForName(Native Method)
        at java.lang.BootClassLoader.findClass(ClassLoader.java:781)
        at java.lang.BootClassLoader.loadClass(ClassLoader.java:841)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:504)
        ... 13 more
Caused by: java.lang.NoClassDefFoundError: Class not found using the boot class loader; no stack available/output.

It would seem that the culprit is java.io.IOException: Failed to remove obsolete file from /data/dalvik-cache/arm/data@[email protected]@[email protected] when searching for dex file /data/app/com.johan.fsc-1/base.apk: Permission denied, but I have not found why it's being invoked for some users and not the majority, and more importantly--how to fix it.

Egarton answered 31/3, 2016 at 20:15 Comment(12)
This might have something to do with the Installation Unsuccessful problem based on the line that says Failed to remove obsolete file ... Permission deniedZulemazullo
I've also been thinking that there might be a connection, but I didn't think the installer actually uses the permissions defined in the manifest.Egarton
Have you tried uninstalling the app from a device before reinstalling?Zulemazullo
As I mentioned, I don't get this crash, and neither do the vast majority of my users. This is a reoccurring crash report that I get from time to time.Egarton
Have you had any changes to the manifest between updates?Stammel
Of course, but this crash was being reported even at the earliest days of the app.Egarton
There is a typo in the manifest in the line android:largeHeap="true">>. xml line ends with >>.Tire
Wow, it appears you're right, it is a typo. I think this may be causing both of my problems. I'll run it with my volunteers and let you know if it was that.Egarton
@JohanZ. was it the typo?Slusher
Hard to say since the crash is non-reproducible and the only reports I get is from seldom users. But proximity the typo's proximity to the intent filter there is a high chance it is. Regardless, unless someone delivers a detailed answer as to why this exception occurs, the bounty will go to suku, since I had no report of this crash for days since the fix.Egarton
Unless you are putting together your class names using a Class <?>, then I would go with suku's Possible Cause 1 - it's really close to the problem area and I do believe that typo will interfere with the PackageManager being able to load that particular class. The clue is here: Suppressed: java.lang.ClassNotFoundException: com.johan.fsc.MainActivityTumbler
There must be something wrong at the package name/app id in build.gradle.Messiah
T
3

Possible Cause 1: There is a typo in the manifest in the line android:largeHeap="true">>. xml line ends with >>. This may be preventing the Intent-Filter from executing.

Possible Cause 2: My guess is that the phone is searching for a class <PackageName>.<PackageName>.<ClassName> instead of <PackageName>.<ClassName> . So definitely <PackageName>.<PackageName>.<ClassName> is not found and ClassNotFoundException would be the result. In android studio, in the manifest, by default activity name is written like this: android:name=".<ClassName>" instead of android:name="<PackageName>.<ClassName>" . You can give this a try.

Most phones may be checking whether packagename is added before the class name in the manifest. If it is added then they don't add it while searching of the class. While few phones must be adding the package name by default while searching for the class. Hence, they cannot find your class.

Tire answered 6/4, 2016 at 1:45 Comment(5)
I think it's more of a problem with the glaring, error-less typo that you mention rather than this. This was a solution I adopted to avoid yet another ClassNotFoundException.Egarton
That typo didn't give me an error when I tried it. Great then please award me the bountyTire
I think you should use your answer in my other question, #36314769, because while your answer may be the one that fixes it, it still isn't a solid explanation for the ClassNotFoundException. Post your answer there and I'll reward you the bounty once the testers confirm it can be installed again. If it turns out it causes THIS error as well, you'll get both bounties.Egarton
I'll grant you the bounty a day before it expires seeing as there's still no concise way to determine whether it did cause the crash or not, however it does seem quite convincing that it did. Make sure you make a small edit to your answer to include it when I do. I did not have this crash reported ever since, however.Egarton
Turns out this did not help.Egarton
S
0

Certainly, you're naming your activity wrong. An activity CAN NOT consist the package's name in its name attribute.

Since you're already defining the package name here
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.johan.fsc">

You shouldn't mention that name here
<activity android:name="com.johan.fsc.MainActivity"

The only situation you should use package name along with a class's name is when the java class resides in a different package, as done in import statements.
Even if your activity is not present in the src folder and is instead present in a nested folder, android studio should handle the linking of manifest and the activity itself. Yet again, package name shouldn't be used there.

Slusher answered 7/4, 2016 at 18:6 Comment(1)
Absolutely cannot? The app works with this configuration. Not only that, it's a method I adopted from reading another question with the ClassNotFoundException error, thus only a recent change. It made no difference, so I'll be reverting to the default format.Egarton

© 2022 - 2024 — McMap. All rights reserved.