0

I am trying to dynamically load an actor from an external jar and then launch that actor into the ActorSystem. I want a plug-in style architecture for loading actors. So far I am tried the following code:

val loader = new URLClassLoader(Array(new URL("file:///<path>/plugin.jar")))
val clazz = loader.loadClass("d2e.Inst").asInstanceOf[Class[Actor]]

This part works fine, however if I start and ActorSystem and attempt to launch my new actor:

val system = ActorSystem.create("mysys")
val actor = system.actorOf(Props(clazz), "myactor")

I get the following exception:

akka.ConfigurationException: configuration problem while creating
...
Caused by: java.lang.IllegalArgumentException: unknown actor creator [class d2e.Inst]
at akka.actor.Props.cachedActorClass(Props.scala:207)
at akka.actor.Props.actorClass(Props.scala:327)
at akka.dispatch.Mailboxes.getMailboxType(Mailboxes.scala:124)
at akka.actor.LocalActorRefProvider.actorOf(ActorRefProvider.scala:718)

Digging deeper into the Props.scala file, I found that the error arises from isAssignableFrom being used. I tested it a bit and I found that there is the following confusing behavior:

println(clazz.isInstanceOf[Class[Actor]])         // returns true
println(classOf[Actor].isAssignableFrom(clazz))   // returns false

Is there a way around this behavior? I'm guessing it has something to do with the Actor class being defined in the system classloader and the URLclassloader. Is my plugin attempt even possible?

Oh, and I am using akka 2.2.1 with scala 2.10.2

EDIT

To clarify one point, the clazz.isInstanceOf[Class[Actor]] will be true for anything because of type erasure.

Ben Schmidt
  • 261
  • 2
  • 13
  • It is true that class identity is scoped to the classloader that brought it in, so loading the same `.class` file via two different classloaders makes them effectively unrelated classes with no compatibility of instances created from them. — I have written similiar plug-in schemes (I call it the Poor Man's Plug-In Pattern) but I've always arranged to have the classes so loaded available in the classpath supplied when the JVM was launched. – Randall Schulz Nov 22 '13 at 14:55
  • That last part is throwing me... If you have have loaded the classes at JVM launch, how are you implementing a plugin scheme? – Ben Schmidt Nov 22 '13 at 15:25
  • By loading them on demand and via reflection, not statically. – Randall Schulz Nov 22 '13 at 17:25
  • [I got distracted while editing the previous comment and time limit expired. Here's what I wanted to add…] In some cases it's sufficient to provide a means of augmenting the classpath when you launch the tool, via command-line option. I never ever have my users (including me as user) launch the JVM directly. I always have custom launcher scripts where it's easy to accommodate options to, say, augment the class-path. – Randall Schulz Nov 22 '13 at 17:46
  • I assume you're not giving it a proper parent classloader. I'd recommend to create an Akka Extension and then use the ExtendedActorSystem's DynamicAccess' classLoader as parent – Viktor Klang Nov 22 '13 at 17:56

0 Answers0