ClassCastException: Die Schnittstelle akka.actor.Scheduler kann nicht von der Klasse akka.actor.LightArrayRevolverScheduler zugewiesen werden

9

Ich versuche, etwas zu betreiben, das ich seit Monaten unter verschiedenen Bedingungen erfolgreich betreibe. Ich benutze akka-actor_2.11 2.3.4 mit scala-library 2.11.7 aus einer Java-Anwendung, auf der Java 7 läuft. Wie ich schon sagte, derselbe Code hat seit Monaten funktioniert. Unter den letzten Umständen bekomme ich Folgendes:

%Vor%

Der fragliche Aufruf lautet: system= ActorSystem.create("MyActorSystem");

Dieser Aufruf findet im Konstruktor für eine Klasse statt, die über die Reflektion ala getConstructor(...).newInstance(...) dynamisch geladen wird.

Das Problem ist aufgetreten, wenn ein Benutzer der verteilten Berechnungsumgebung, auf den er basiert, versucht, einen Job auszuführen, der dynamisch einen Job instantiiert, der einen Job dynamisch instantiiert (zwei Ebenen der reflektiven Instanziierung). Grundsätzlich so etwas wie diese Pseudo-Anrufliste:

%Vor%

Wenn ich den exakt gleichen Code auf die folgende Weise ausführen:

%Vor%

Alles funktioniert.

Meine Frage ist, ob es in Java hinter den Kulissen irgendeine Stateful-Loader-bezogene Magie gibt, so dass Akkas Annahmen über seinen Zustand falsch sind. Ähnliche Probleme, die ich gefunden habe ( Akka ActorSystem-Erstellungsproblem ), schienen mit threading / scala repl zu tun zu haben Aufruf, aber mein Code ist single-threaded und auf die gleiche Weise in den beiden oben genannten Erfolg und Fehler aufgerufen. Der problematische Aufruf erfolgt, soweit ich das beurteilen kann, nur mit einem Unterschied in der Tiefe des Call-Stacks.

Ich würde mich über jeden Input von akka gurus freuen!

    
mephicide 29.03.2016, 17:20
quelle

1 Antwort

1

Wenn jemand darüber stolpert; Das Problem in meinem Fall war, dass ich einen Scala-Interpreter im selben Prozess benutzte, der auch Akka verwenden könnte. Andere Szenarien mit mehreren Klassenladeprogrammen weisen möglicherweise das gleiche Problem auf. Hier ist die Lösung für meinen Fall:

  • Speichern Sie den Klassenlader, den ich mag (den, der akka-Bibliotheken geladen hat), in einem statischen Feld bei der Programminitialisierung mit private static ClassLoader ourClassLoader = CmdLineMain.class.getClassLoader();
  • Nachdem Sie den Scala-Interpreter (der den Classloader scheinbar durch einen anderen ersetzt) ​​verwendet, rufen Sie Thread.currentThread().setContextClassLoader(ourClassLoader); auf.

Mein Programm ist single-threaded, aber es gibt sicherlich andere Möglichkeiten, das Problem zu lösen, so dass jeder Thread seinen eigenen Loader führt. Das geht über den Rahmen dieses Beitrags hinaus;)

    
mephicide 29.12.2016, 20:17
quelle

Tags und Links