2016-11-14 6 views
1

Ich habe ein Problem beim Laden der Nashorn Script Engine in einer Karaf + Felix + OpenJDK8 Umgebung: new ScriptEngineManager().getEngineByName("nashorn") gibt in dieser Umgebung null zurück. Meine Tests, die diesen Code verwenden, werden erfolgreich ausgeführt, egal ob sie von maven (mit derselben JDK-Installation auf dem Linux/Debian-Server) oder in der IDE auf meinem Windows-Rechner ausgeführt werden.Nashorn ScriptEngine nicht gefunden/registriert bei Karaf + Felix (openJDK)

Dies sind die Schritte, die ich überprüft:

  • Karaf läuft mit JDK8 die richtige ext mit verwiesen:

    > ps aux | Grep Karaf | grep java
    ... -Djava.ext.dirs =/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/ext:/usr/lib/jvm/java-8-openjdk-amd64/lib/ext: /media/sf_Development/app/apache-karaf-4.0.6/lib/ext ...

  • Die nashorn.jar verfügbar:

    > jar tf/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/ext/nashorn.jar | grep NashornScriptEngineFactory
    jdk/nashorn/api/scripting/NashornScriptEngineFactory.class

  • Bei <karaf>/etc/config.properties die org.osgi.framework.bootdelegation Eigenschaft enthält jdk.nashorn.* nach this question

  • Mein Bündel auch importiert/erfordert jdk.nashorn, die erfolgreich von felix gelöst ist :

    > bündel: anforderungen my-bundle | grep -A 1 nashorn
    ...
    osgi.wiring.package; (osgi.wiring.package = jdk.nashorn) gelöst von:
      osgi.wiring.package; jdk.nashorn 0.0.0 von org.apache.felix.framework [0]
    ...

Durch die Art und Weise zurück die Liste von new ScriptEngineManager().getEngineFactories() leer ist, so dass es keine Option ist eine andere zu versuchen, Skript-Engine.

Hat jemand eine Ahnung, was schief gelaufen ist? Mußte ich einen Cache leeren, bevor ich Karaf neu starte?

Antwort

2

Der Standardkonstruktor von ScriptEngineManager verwendet den Threadkontextklassenlader mit dem Dienstladeprogramm. Wenn der Threadkontextklassenlader nicht an den Erweiterungsklassenlader delegiert wird, wird Nashorn oder eine andere Engine, die nur für den Erweiterungslader sichtbar ist, nicht gefunden! Es gibt zwei Lösungen:

  1. Sie vorübergehend den Thread-Kontext-Klasse-Loader kann entweder auf Verlängerung Lader oder ein Lader, die ihm die Delegierten - nur vor dem Erstellen von Script Objekt (und Sie Reset stellen Sie den alten Thread-Kontext Class-Loader nach dem Auffinden der Motor).
  2. Sie können den ClassLoader-Konstruktor von ScriptEngineManager verwenden (siehe auch: https://docs.oracle.com/javase/8/docs/api/javax/script/ScriptEngineManager.html#ScriptEngineManager-java.lang.ClassLoader-), indem Sie einen entsprechenden ClassLoader übergeben.Auch hier können Sie den Erweiterungsklassenlader oder einen Loader, der an den Erweiterungsklassenlader delegiert, weiterleiten, sodass die für den Erweiterungslader sichtbaren Engines vom Dienstlademechanismus gefunden werden können.
+1

Danke für den Hinweis! Es funktioniert mit dem Systemklassenlader: 'new ScriptEngineManager (ClassLoader.getSystemClassLoader())'. Ist das der richtige Weg? Es sieht für mich irgendwie eklig aus. – rudi

+0

Wenn der "richtige" Threadkontextklassenlader nicht gesetzt ist, verwenden Sie eine andere veröffentlichte API (der ScriptEngineManager-Klasse). Also, es ist in Ordnung! –

Verwandte Themen