2016-03-29 19 views
9

Sto cercando di eseguire qualcosa che ho eseguito con successo in una varietà di condizioni per mesi. Sto usando akka-actor_2.11 2.3.4 con scala-library 2.11.7 da un'applicazione Java con Java 7. Come ho detto, lo stesso codice ha funzionato per mesi. Date le circostanze più recenti, sto ottenendo il seguente:ClassCastException: interfaccia akka.actor.Scheduler non è assegnabile dalla classe akka.actor.LightArrayRevolverScheduler

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) 

La chiamata in questione è: system= ActorSystem.create("MyActorSystem");

Questa chiamata avviene nel costruttore per una classe, che viene caricato in modo dinamico, tramite riflessione ala getConstructor(...).newInstance(...) .

Il problema è sorto quando un utente dell'ambiente di calcolo distribuito ho scritto che questo è basato sul tentativo di eseguire un lavoro che crea dinamicamente un lavoro che crea dinamicamente un lavoro (2 livelli di istanziazione riflessiva). In sostanza, qualcosa di simile a questa lista chiamate pseudo:

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

caso corro lo stesso codice esattamente nel modo seguente:

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

Tutto funziona.

La mia domanda è se ci sono alcuni eventi di magia legati al caricatore classe state behind the scene in Java in modo tale che le ipotesi di Akka sul suo stato non siano corrette. Problemi simili che ho trovato (Akka ActorSystem creation issue) sembravano avere a che fare con la chiamata threading/scala repl, ma il mio codice è a thread singolo e invocato allo stesso modo sia nei casi di successo che di fallimento sopra. L'invocazione problematica si verifica solo con una differenza nella profondità dello stack di chiamate, per quanto posso dire finora.

Apprezzerei qualsiasi input dai guru di akka!

+2

Supponendo che la classe 'akka.actor.LightArrayRevolverScheduler', infatti, implementa l'interfaccia' akka.actor.Scheduler', le uniche spiegazioni possibili per l'eccezione presentata nella traccia dello stack. ruota attorno a affari divertenti con 'ClassLoader's. Temo di trovare la documentazione di Akka piuttosto carente nei dettagli pertinenti, tuttavia, quindi non ho alcuna soluzione da offrire. –

+0

Sono in grado di aggirare il problema con un utilizzo del pattern Singleton che incapsula i componenti ActorSystem rilevanti, che posso inizializzare all'inizio del mio processo java e ottenerlo al bisogno. Non ho mai dovuto fare questo fino a quando questo strano problema non è saltato fuori, e forse qualcun altro avrà un problema simile e forse trarrà beneficio da una spiegazione di qualcuno in-the-know. – mephicide

+0

Forse stai avendo problemi con la versione di dipendenza. Cosa usi per la costruzione? Se usi Maven e un Pom, cosa succede se imponi le versioni usando ...? –

risposta

1

Se qualcun altro si imbatte in questo; il problema nel mio caso era che stavo usando un'interprete scala all'interno dello stesso processo che potrebbe anche fare uso di Akka. Altri scenari con più classloader possono presentare lo stesso problema. Ecco la soluzione per il mio caso:

  • Salvare il programma di caricamento classe che mi piace (quello che ha caricato Akka librerie) in un campo statico al momento dell'inizializzazione programma con private static ClassLoader ourClassLoader = CmdLineMain.class.getClassLoader();
  • Dopo aver usato l'interprete Scala (che sostituisce a quanto pare il classloader con uno che gli piace), chiamare Thread.currentThread().setContextClassLoader(ourClassLoader);

il mio programma è a thread singolo, ma ci sono sicuramente altri modi per risolvere il problema in modo tale che ogni thread mantiene il proprio caricatore. Questo è oltre lo scopo di questo post;)