【问题标题】:Occasionally receiving WarningContextClassLoader instead of PathClassLoader causing flyway to crash偶尔收到 WarningContextClassLoader 而不是 PathClassLoader 导致 flyway 崩溃
【发布时间】:2017-04-04 17:25:23
【问题描述】:

上下文

在我的 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 级别 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 的支持。 pull request 已提交。

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

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

【问题讨论】:

    标签: java android classloader flyway


    【解决方案1】:

    commit message adding WarningContextClassLoader 提供了不错的信息。我猜想传递活动的上下文可能会有所帮助。

    【讨论】:

    • 不,它没有。我检查了(flyway 是开源的),上下文不用于抓取类加载器。实际上 flyway 只是像这样初始化它的类加载器:private ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); 但是感谢分享!
    【解决方案2】:

    什么是 LoadedApk.WarningContextClassLoader ?

    为什么有时用它来代替 dalvik.system.PathClassLoader ?

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

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

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

    解决方案

    【讨论】:

      猜你喜欢
      • 2016-03-21
      • 1970-01-01
      • 1970-01-01
      • 2014-11-25
      • 2012-08-19
      • 2016-12-17
      • 2018-08-23
      • 1970-01-01
      • 2012-09-22
      相关资源
      最近更新 更多