2016-11-21 16 views
-1

Contextраздавался прием WarningContextClassLoader вместо PathClassLoader вызывает пролетный врезаться

В моем андроид приложения, я использую пролетный путь обновить мою Db схему. До сих пор у меня есть одна и только одна миграция, которая создает 3 таблицы. Простой и обычный бизнес для пролета. Он работает очень хорошо ... большую часть времени! Иногда он выходит из строя с этой ошибкой (полный стек) по настоящему Договору:

java.lang.ClassCastException: android.app.LoadedApk$WarningContextClassLoader 
cannot be cast to dalvik.system.PathClassLoader 

У меня есть несколько вопросов, связанных с этой ошибкой:

  • Что такое LoadedApk.WarningContextClassLoader?
  • Почему это иногда используется вместо dalvik.system.PathClassLoader?
  • Это ошибка в моем приложении, в Android-системе или в Flyway?

Я также заметил, что я могу вводить явно загрузчик классов внутри пролетного (Flyway.setClassLoader())

  • Как я могу получить наверняка правый загрузчик классов?

Обратите внимание, что я вставляю контекст приложения в пролетный, а не в конкретный контекст активности.

Версии

Я использую org.flywaydb: пролетный путь-ядро: 4.0.2

Я заметил эту проблему в Android 4.2.2 (Jellybean, уровень апи 17) и 4.4 (KitKat, API уровень 19). AFAIK, это никогда не происходило на более высоких версиях.

Стек след

Exception java.lang.RuntimeException: Unable to start activity ComponentInfo{com.mycompany.myapp.free.debug/com.mycompany.MainActivity}: java.lang.ClassCastException: android.app.LoadedApk$WarningContextClassLoader cannot be cast to dalvik.system.PathClassLoader 
    android.app.ActivityThread.performLaunchActivity (ActivityThread.java:2306) 
    android.app.ActivityThread.handleLaunchActivity (ActivityThread.java:2358) 
    android.app.ActivityThread.access$600 (ActivityThread.java:156) 
    android.app.ActivityThread$H.handleMessage (ActivityThread.java:1340) 
    android.os.Handler.dispatchMessage (Handler.java:99) 
    android.os.Looper.loop (Looper.java:153) 
    android.app.ActivityThread.main (ActivityThread.java:5299) 
    java.lang.reflect.Method.invokeNative (Method.java) 
    java.lang.reflect.Method.invoke (Method.java:511) 
    com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run (ZygoteInit.java:833) 
    com.android.internal.os.ZygoteInit.main (ZygoteInit.java:600) 
    dalvik.system.NativeStart.main (NativeStart.java) 

Caused by java.lang.ClassCastException: android.app.LoadedApk$WarningContextClassLoader cannot be cast to dalvik.system.PathClassLoader 
    org.flywaydb.core.internal.util.scanner.classpath.android.AndroidScanner.<init> (AndroidScanner.java:46) 
    org.flywaydb.core.internal.util.scanner.Scanner.<init> (Scanner.java:38) 
    org.flywaydb.core.Flyway.execute (Flyway.java:1353) 
    org.flywaydb.core.Flyway.info (Flyway.java:1040) 
    com.mycompany.db.FlywayHelper.info (FlywayHelper.java:54) 
    com.mycompany.db.FlywayHelper.migrate (FlywayHelper.java:45) 
    com.mycompany.db.GW2DatabaseHelper.migrate (GW2DatabaseHelper.java:56) 
    com.mycompany.db.DbInit.initKeyGuild (DbInit.java:62) 
    com.mycompany.db.DbInit.init (DbInit.java:42) 
    com.mycompany.business.BootApp.boot (BootApp.java:79) 
    com.mycompany.MainActivity.onCreate (MainActivity.java:51) 
    android.app.Activity.performCreate (Activity.java:5122) 
    android.app.Instrumentation.callActivityOnCreate (Instrumentation.java:1081) 
    android.app.ActivityThread.performLaunchActivity (ActivityThread.java:2270) 
    android.app.ActivityThread.handleLaunchActivity (ActivityThread.java:2358) 
    android.app.ActivityThread.access$600 (ActivityThread.java:156) 
    android.app.ActivityThread$H.handleMessage (ActivityThread.java:1340) 
    android.os.Handler.dispatchMessage (Handler.java:99) 
    android.os.Looper.loop (Looper.java:153) 
    android.app.ActivityThread.main (ActivityThread.java:5299) 
    java.lang.reflect.Method.invokeNative (Method.java) 
    java.lang.reflect.Method.invoke (Method.java:511) 
    com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run (ZygoteInit.java:833) 
    com.android.internal.os.ZygoteInit.main (ZygoteInit.java:600) 
    dalvik.system.NativeStart.main (NativeStart.java) 

Исследования обновление

Хотя его цель не ясна мне, LoadedApk.WarningContextClassLoader кажется, действительный загрузчик классов, а затем должен быть поддержан Flyway , A pull request.

В период, обходной путь должен быть реализован, чтобы ввести ожидаемый загрузчик классов:

private void injectClassLoader(Flyway flyway) { 
    ClassLoader classLoader = flyway.getClassLoader(); 
    if (classLoader != null && !(classLoader instanceof PathClassLoader)){ 
     flyway.setClassLoader(classLoader.getParent()); 
    } 
} 

ответ

0

Что такое LoadedApk.WarningContextClassLoader?

Почему это иногда используется вместо dalvik.system.PathClassLoader?

Не совсем уверен, но цель этого конкретного загрузчика классов, по-видимому, предупреждает пользователя о том, что его пакет может делиться своей виртуальной машиной с другими пакетами.More info here, благодаря @orip.

Является ли это ошибкой в ​​моем приложении, в системе Android или в пролете?

В любом случае WarningContextClassLoader по-прежнему является допустимым загрузчиком классов и должен быть принят пролетным путем. Литой, сделанный в AndroidScanner, был просто бесполезен.

Решение

1

Там приличная информация commit message adding WarningContextClassLoader. Я бы предположил, что передача контекста активности может помочь.

+0

Нет, это не так. Я проверил (flyway is open-source), контекст не используется для захвата загрузчика классов. Фактически flyway просто инициализирует свой загрузчик классов следующим образом: 'private ClassLoader classLoader = Thread.currentThread(). GetContextClassLoader();' Но спасибо за обмен! – Benoit