java .lang.NoClassDefFoundError: xxx.xxx.xxx.Xxx $ Xxx (только Dalvik) - PullRequest
1 голос
/ 13 июля 2020

Я написал библиотеку, в которой есть реализация общих предпочтений, в которой она уменьшает количество сообщений об ошибках ANR, которые работали до сегодняшнего дня, одно приложение начало выдавать NoClassDefFoundError. Этого не происходит ни в каких других приложениях, в которых есть библиотека, и это происходит только при сборке debug , этого не происходит при сборке выпуска. Но это по-прежнему важно, потому что это означает, что я в конечном итоге столкнусь с этой проблемой в будущем.

Обратите внимание, что приложение использовало multidex в течение года при правильной реализации, что означает, что attachBaseContext переопределено, multiDexEnabled уже верно et c ...

Следует также упомянуть, что метод getSharedPreferences переопределен в классе приложения.

public class AppClass extends MultiDexApplication
{
    // onCreate and rest of the code    

    // Return a special SharedPreferences instance
    // to apply changes properly.
    @Override
    public SharedPreferences getSharedPreferences(String name, int mode)
    {
        return SharedPreferencesWrapper.getInstance(name, super.getSharedPreferences(name, mode));
    }
}

APK большой, в нем 4 classes.dex файлов, и я заметил, что класс SharedPreferences, который пытается загрузить экземпляр SharedPreferences.Editor, находится в classes.dex, тогда как класс, реализующий редактор, находится в classes2.dex. Я считаю, что это причина того, что программа не работает с таким исключением:

E/AndroidRuntime: FATAL EXCEPTION: firebase-iid-executor
    Process: com.test.app, PID: 4226
    java.lang.NoClassDefFoundError: com.mylibrary.SharedPreferencesWrapper$SharedPreferencesEditor
        at com.mylibrary.SharedPreferencesWrapper.edit(SharedPreferencesWrapper.java:311)
        at com.google.firebase.iid.zzaz.zzb(com.google.firebase:firebase-iid@@20.2.1:53)
        at com.google.firebase.iid.FirebaseInstanceId.zzl(com.google.firebase:firebase-iid@@20.2.1:70)
        at com.google.firebase.iid.FirebaseInstanceId.zza(com.google.firebase:firebase-iid@@20.2.1:159)
        at com.google.firebase.iid.zzk.then(com.google.firebase:firebase-iid@@20.2.1)
        at com.google.android.gms.tasks.zzg.run(com.google.android.gms:play-services-tasks@@17.0.2:2)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
        at com.google.android.gms.common.util.concurrent.zza.run(com.google.android.gms:play-services-basement@@17.2.1:6)
        at java.lang.Thread.run(Thread.java:841)

Я также вижу, что dalvik тоже жалуется на то, что не нашел класс:

E / dalvikvm: не удалось найти класс com.mylibrary.SharedPreferencesWrapper $ SharedPreferencesEditor, на который ссылается метод com.mylibrary.SharedPreferencesWrapper.edit

Здесь он не работает:

public class SharedPreferencesWrapper implements SharedPreferences
{
    // rest of the methods

    @Override
    public Editor edit()
    {
        // This is where it fails
        return new SharedPreferencesEditor();
    }

    // The wrapper editor class that performs modifying the map
    // and writes to files etc...
    // This class is not in the same .dex file as the parent class.
    // Notice that the class isn't "static", but making it static
    // and passing a reference doesn't help either.
    public class SharedPreferencesEditor implements SharedPreferences.Editor
    {
         // some class variables, no static block defined,
         // no exceptions are thrown in the constructor.
         // It doesn't even reach the constructor.
    }
}

В этом блоке кода после создания файла APK я вижу, что SharedPreferencesWrapper находится в classes.dex, а SharedPreferencesWrapper$SharedPreferencesEditor находится в classes2.dex. Я предполагаю, что он не может найти класс, потому что он находится в другом файле .dex, но я не знаю, как я могу поместить его в тот же файл dex.

Я также заметил, что <clinit> существует для SharedPreferencesWrapper в анализаторе APK, но не SharedPreferencesWrapper$SharedPreferencesEditor. Это кажется мне важным , но я не уверен, как его решить.

Изменить : <clinit> начал появляться после добавления stati c переменная в класс. По-видимому, это связано с тем, что есть несколько классов, которые не имеют определения <clinit>, но все равно отлично работают. Однако исключение все еще сохраняется.

То, что я пробовал до сих пор:

  1. Перемещение класса редактора в его собственный файл и передача самого экземпляра оболочки общих настроек (потому что он необходимо),
  2. Создание класса редактора c и передача ссылки на объект,
  3. Использование старой версии gradle и старой версии multi-dex (в настоящее время я использую 2.0. 1),
  4. Очистка проекта, повторная сборка проекта, удаление папок сборки, удаление кешей, аннулирование кеша и параметр перезапуска, повторный импорт проекта из git et c ... всего этого.

Есть решение? Я понятия не имею, что делать. Любая помощь приветствуется, большое спасибо.

...