I am trying to run something I have been successfully running under a variety of conditions for months. I am using akka-actor_2.11 2.3.4 with scala-library 2.11.7 from a Java application running Java 7. Like I said, the same code has worked for months. Under the most recent circumstances, I am getting the following:
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)
The call in question is:
system= ActorSystem.create("MyActorSystem");
This call happens in the constructor for a class, which is loaded dynamically, via reflection ala getConstructor(...).newInstance(...)
.
The issue has arisen when a user of the distributed computation environment I wrote that this is based on tries to execute a job that dynamically instantiates a job that dynamically instantiates a job (2 levels of reflective instantiation). Basically, something like this pseudo call list :
reflectivelyCreate(job)
job.reflectivelyCreate(job2)
job2.instantiateActorSystem()
<fail>
If I run the exact same code in the following manner:
reflectivelyCreate(job2)
job2.instantiateActorSystem()
<success>
Everything works.
My question is whether there is some stateful class loader-related magic happening behind-the-scenes in Java such that Akka's assumptions about its state are incorrect. Similar issues I found (Akka ActorSystem creation issue) seemed to have to do with threading / scala repl invocation, but my code is single-threaded, and invoked the same way in both the success and failure cases above. The problematic invocation occurs only with a difference in the depth of the call stack as far as I can tell so far.
I would appreciate any input from akka gurus!
If anyone else stumbles across this; the problem in my case was that I was using a scala interpreter within the same process that might also make use of Akka. Other multiple-classloader scenarios may exhibit the same issue. Here is the fix for my case:
private static ClassLoader ourClassLoader = CmdLineMain.class.getClassLoader();
Thread.currentThread().setContextClassLoader(ourClassLoader);
My program is single-threaded, but there are certainly other ways to solve the problem such that each thread maintains its own loader. That is beyond the scope of this post ;)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With