【问题标题】:ClassCastException: interface akka.actor.Scheduler is not assignable from class akka.actor.LightArrayRevolverSchedulerClassCastException:接口 akka.actor.Scheduler 不能从类 akka.actor.LightArrayRevolverScheduler 分配
【发布时间】:2016-03-29 17:20:06
【问题描述】:

我正在尝试运行几个月来在各种条件下成功运行的东西。我正在运行 Java 7 的 Java 应用程序中使用 akka-actor_2.11 2.3.4 和 scala-library 2.11.7。就像我说的,相同的代码已经运行了几个月。在最近的情况下,我得到以下信息:

java.lang.ClassCastException: interface akka.actor.Scheduler is not assignable from class akka.actor.LightArrayRevolverScheduler
at akka.actor.ReflectiveDynamicAccess$$anonfun$getClassFor$1.apply(DynamicAccess.scala:69)
at akka.actor.ReflectiveDynamicAccess$$anonfun$getClassFor$1.apply(DynamicAccess.scala:66)
at scala.util.Try$.apply(Try.scala:192)
at akka.actor.ReflectiveDynamicAccess.getClassFor(DynamicAccess.scala:66)
at akka.actor.ReflectiveDynamicAccess.createInstanceFor(DynamicAccess.scala:84)
at akka.actor.ActorSystemImpl.createScheduler(ActorSystem.scala:677)
at akka.actor.ActorSystemImpl.<init>(ActorSystem.scala:576)
at akka.actor.ActorSystem$.apply(ActorSystem.scala:142)
at akka.actor.ActorSystem$.apply(ActorSystem.scala:109)
at akka.actor.ActorSystem$.create(ActorSystem.scala:57)
at akka.actor.ActorSystem.create(ActorSystem.scala)

有问题的电话是: system= ActorSystem.create("MyActorSystem");

此调用发生在类的构造函数中,该类通过反射ala getConstructor(...).newInstance(...) 动态加载。

当我写的分布式计算环境的用户尝试执行动态实例化作业的作业时,问题就出现了,该作业动态实例化作业(2 级反射实例化)。基本上,类似这样的伪调用列表:

reflectivelyCreate(job)
job.reflectivelyCreate(job2)
job2.instantiateActorSystem()
<fail>

如果我以以下方式运行完全相同的代码:

reflectivelyCreate(job2)
job2.instantiateActorSystem()
<success>

一切正常。

我的问题是,Java 中是否有一些与有状态类加载器相关的魔法发生在幕后,以至于 Akka 关于其状态的假设是不正确的。我发现的类似问题(Akka ActorSystem creation issue)似乎与线程/scala repl 调用有关,但我的代码是单线程的,并且在上述成功和失败情况下都以相同的方式调用。据我所知,有问题的调用仅在调用堆栈的深度有所不同时才会发生。

感谢 akka 大师的任何意见!

【问题讨论】:

  • 假设类akka.actor.LightArrayRevolverScheduler 确实实现了接口akka.actor.Scheduler,那么对堆栈跟踪中出现的异常的唯一可能解释围绕着ClassLoaders 的有趣业务。但是,恐怕我发现 Akka 的文档缺乏相关的详细信息,因此我无法提供解决方案。
  • 我能够使用封装相关 ActorSystem 组件的单例模式使用来解决问题,我可以在我的 java 进程开始时对其进行初始化并根据需要获取。在出现这个奇怪的问题之前,我从来不需要这样做,也许其他人也会遇到类似的问题,并且可能会从知情人的解释中受益。
  • 也许你遇到了依赖版本问题。你用什么建筑?如果您使用 maven 和 pom,如果您使用 ... 固定版本会发生什么?

标签: java akka classcastexception


【解决方案1】:

如果其他人偶然发现了这一点;就我而言,问题是我在可能也使用 Akka 的同一进程中使用了 scala 解释器。其他多类加载器方案可能会出现相同的问题。这是我的情况的解决方法:

  • 在程序初始化时使用private static ClassLoader ourClassLoader = CmdLineMain.class.getClassLoader();将我喜欢的类加载器(加载akka库的类加载器)保存在一个静态字段中
  • 使用 scala 解释器(显然用它喜欢的类加载器替换了类加载器)后,调用Thread.currentThread().setContextClassLoader(ourClassLoader);

我的程序是单线程的,但当然还有其他方法可以解决这个问题,比如每个线程都维护自己的加载器。这超出了本文的范围;)

【讨论】:

    猜你喜欢
    • 2016-03-05
    • 2012-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-11
    • 1970-01-01
    相关资源
    最近更新 更多