偶尔会收到WarningContextClassLoader而不是PathClassLoader导致flyway崩溃

时间:2016-11-21 10:37:07

标签: java android classloader flyway

上下文

在我的Android应用中,我使用 flyway 来更新我的Db架构。到目前为止,我只有一个迁移,它创建了3个表。飞路的简单和平常的业务。它确实很好用......大多数时候!有时它崩溃了这个错误(下面的完整堆栈):

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

我有几个与此错误相关的问题:

  • 什么是LoadedApk.WarningContextClassLoader?
  • 为什么有时会使用它而不是dalvik.system.PathClassLoader?
  • 这是我的应用,Android系统或Flyway中的错误吗?

我还注意到我可以在flyway(Flyway.setClassLoader())中明确地注入类加载器

  • 如何确保正确的类加载器?

请注意,我在Flyway中注入应用程序上下文,而不是特定活动的上下文。

版本

我使用的是org.flywaydb:flyway-core:4.0.2

我在Android 4.2.2(JellyBean,api level 17)和4.4(KitKat,api level 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支持。已提交pull request

在这两者之间,需要实现一个解决方法,以注入预期的类加载器:

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

2 个答案:

答案 0 :(得分:1)

commit message adding WarningContextClassLoader提供了不错的信息。我猜想通过活动的背景可能有所帮助。

答案 1 :(得分:0)

  

什么是LoadedApk.WarningContextClassLoader?

     

为什么有时使用它而不是dalvik.system.PathClassLoader?

不太确定,但这个特定类加载器的目的似乎警告用户它的包可以与其他包共享其虚拟机。 More info here,感谢@orip。

  

这是我的应用,Android系统或Flyway中的错误吗?

无论如何,WarningContextClassLoader仍然是一个有效的类加载器,并且必须被flyway接受。在AndroidScanner中制作的演员阵容毫无用处。

<强>解决方案