Syntey
Syntey

Reputation: 147

ClassNotFoundException on Worker class

I'm getting a lot of strange errors in production, that only happens to a few users, so 99% of users are okay.

java.lang.Error: java.lang.ClassNotFoundException: com.packagename.core.Translations.TranslationWorker
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1119)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
        at java.lang.Thread.run(Thread.java:818)

Caused by: java.lang.ClassNotFoundException: com.packagename.core.Translations.TranslationWorker
        at java.lang.Class.classForName(Class.java:-2)
        at java.lang.Class.forName(Class.java:324)
        at java.lang.Class.forName(Class.java:285)
        at com.packagename.core.translations.TranslationWorkerFactory.createWorker(TranslationWorkerFactory.kt:19)
        at androidx.work.WorkerFactory.createWorkerWithDefaultFallback(WorkerFactory.java:83)
        at androidx.work.impl.WorkerWrapper.runWorker(WorkerWrapper.java:242)
        at androidx.work.impl.WorkerWrapper.run(WorkerWrapper.java:136)
        at androidx.work.impl.utils.SerialExecutor$Task.run(SerialExecutor.java:91)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
        at java.lang.Thread.run(Thread.java:818)

Caused by: java.lang.ClassNotFoundException: Didn't find class "com.packagename.core.Translations.TranslationWorker" on path: DexPathList[[zip file "/system/framework/android.test.runner.jar", zip file "/data/app/com.packagename.appname-2/base.apk", zip file "/data/app/com.packagename.appname-2/split_config.armeabi_v7a.apk", zip file "/data/app/com.packagename.appname-2/split_config.cs.apk", zip file "/data/app/com.packagename.appname-2/split_config.xhdpi.apk"],nativeLibraryDirectories=[/data/app/com.packagename.appname-2/lib/arm, /data/app/com.packagename.appname-2/base.apk!/lib/armeabi-v7a, /data/app/com.packagename.appname-2/split_config.armeabi_v7a.apk!/lib/armeabi-v7a, /data/app/com.packagename.appname-2/split_config.cs.apk!/lib/armeabi-v7a, /data/app/com.packagename.appname-2/split_config.xhdpi.apk!/lib/armeabi-v7a, /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 java.lang.Class.classForName(Class.java:-2)
        at java.lang.Class.forName(Class.java:324)
        at java.lang.Class.forName(Class.java:285)
        at com.packagename.core.translations.TranslationWorkerFactory.createWorker(TranslationWorkerFactory.kt:19)
        at androidx.work.WorkerFactory.createWorkerWithDefaultFallback(WorkerFactory.java:83)
        at androidx.work.impl.WorkerWrapper.runWorker(WorkerWrapper.java:242)
        at androidx.work.impl.WorkerWrapper.run(WorkerWrapper.java:136)
        at androidx.work.impl.utils.SerialExecutor$Task.run(SerialExecutor.java:91)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
        at java.lang.Thread.run(Thread.java:818)

And this is the code of TranslationWorkerFactory. I'm using dagger assisted inject to inject dependencies to a worker class.

class TranslationWorkerFactory @Inject constructor(
    private val workerFactories: Map<Class<out ListenableWorker>, @JvmSuppressWildcards Provider<ITranslationWorkerFactory>>
) : WorkerFactory() {
    override fun createWorker(
        appContext: Context,
        workerClassName: String,
        workerParameters: WorkerParameters
    ): ListenableWorker? {
        val foundEntry =
                workerFactories.entries.find { Class.forName(workerClassName).isAssignableFrom(it.key) }
        val factoryProvider = foundEntry?.value
                ?: throw IllegalArgumentException("unknown worker class _name: $workerClassName")
        return factoryProvider.get().create(appContext, workerParameters)
    }
}

I have no idea why this happens. What does the worker do is download and parse large json, so that could be a reason to throw a exception, but that's just my guess if it could be related.

Anybody know a reason why is this occurring?

Thanks

Upvotes: 1

Views: 939

Answers (1)

Alex Kucherenko
Alex Kucherenko

Reputation: 20307

Most likely you've moved/renamed your worker class (TranslationWorker), for example ​during refactoring.

If yes continue reading.

Steps to reproduce:

  • start the app (old version) and wait for the worker to be started
  • move the worker class to another package, rebuild the app
  • start the app and wait when the system runs the worker

I didn't find fine solution so far. But there is one working option. Main idea - is to replace incorrect path to the worker class with actual in WorkerFactory. More details in this post

Upvotes: 1

Related Questions