Взаимодействие Scala / Clojure работает на ПК, но не на другом с java.lang.ExceptionInInitializerError - PullRequest
0 голосов
/ 26 марта 2012

У меня есть проект, написанный на смеси Java / Scala, в котором я вызываю статический метод (epadEval), предоставляемый сгенерированным классом Clojure (ca.gsimard.spacecraft.client.clojail).

В clojail.clj:
(составлено в отдельную банку с лейненгеном: "lein uberjar")

(ns ca.gsimard.spacecraft.client.clojail
  (:use [clojail core testers])
  (:gen-class
    :name ca.gsimard.spacecraft.client.clojail
    :methods [#^{:static true} [epadEval [String] String]]))

(defn -epadEval
  "Evaluate string s within a clojail sandbox."
  [s]
  (let [writer (java.io.StringWriter.)]
    (*sb* (safe-read (str "(print " s ")")) {#'*out* writer})
    (str writer)))

В main.scala:
(в проекте Eclipse, где я импортирую .jar, сгенерированный ранее Leinengen):

import ca.gsimard.spacecraft.client.clojail
println("Epad: " + clojail.epadEval("(+ 1 2 3)"))

Я разворачиваю проект, собирая толстый флягу и запускаю его:

На ПК1 (Linux):

Epad: 6

На ПК2 (Windows 7):

Exception in thread "main" java.lang.ExceptionInInitializerError
    at clojure.lang.Namespace.<init>(Namespace.java:34)
    at clojure.lang.Namespace.findOrCreate(Namespace.java:176)
    at clojure.lang.Var.internPrivate(Var.java:149)
    at ca.gsimard.spacecraft.client.clojail.<clinit>(Unknown Source)
    at ca.gsimard.spacecraft.client.Epad$.eval(EpadClient.scala:78)
    at ca.gsimard.spacecraft.client.Main$.main(MainClient.scala:25)
    at ca.gsimard.spacecraft.client.Main.main(MainClient.scala)
Caused by: java.lang.NullPointerException
    at clojure.core$eval1697$fn__1698.invoke(core.clj:6135)
    at clojure.core$eval1697.invoke(core.clj:6135)
    at clojure.lang.Compiler.eval(Compiler.java:6465)
    at clojure.lang.Compiler.load(Compiler.java:6902)
    at clojure.lang.RT.loadResourceScript(RT.java:357)
    at clojure.lang.RT.loadResourceScript(RT.java:348)
    at clojure.lang.RT.load(RT.java:427)
    at clojure.lang.RT.load(RT.java:398)
    at clojure.lang.RT.doInit(RT.java:434)
    at clojure.lang.RT.<clinit>(RT.java:316)
    ... 7 more

Я совершенно не понимаю, что происходит: все, что я знаю, это то, что мало что происходит. Похоже, класс Clojure даже не загружается. Добавление команд (println ..) между (ns ..) и (defn ..) вообще ничего не печатает на ПК2, поэтому кажется, что проблема во время загрузки, а не во время вызова.

Обратите внимание, что на том же компьютере с Windows7, где это не удается, я мог бы успешно создать и запустить автономный uberjar только для Clojure с вызовом (-main) метода (-epadEval ..).

Есть идеи, что здесь происходит?

РЕДАКТИРОВАТЬ: у меня это запускалось с java -verbose , как предложено ниже. Из того, что я понимаю, функция epadEval вызывается ДО того, как она даже будет определена! Исключение происходит, когда JVM все еще загружает clojure.core . Я не видел никаких [Загруженных ca.gsimard.spacecraft.client.clojail ...] до этого.

[Loaded clojure.core$eval1697$fn__1698 from __JVM_DefineClass__]
[Loaded clojure.core$eval1697 from __JVM_DefineClass__]
Exception in thread "main" [Loaded java.lang.Throwable$PrintStreamOrWriter from
C:\Program Files\Java\jre7\lib\rt.jar]
[Loaded java.lang.Throwable$WrappedPrintStream from C:\Program Files\Java\jre7\lib\rt.jar]
[Loaded java.util.IdentityHashMap$KeySet from C:\Program Files\Java\jre7\lib\rt.jar]
java.lang.ExceptionInInitializerError
    at clojure.lang.Namespace.<init>(Namespace.java:34)
    at clojure.lang.Namespace.findOrCreate(Namespace.java:176)
    at clojure.lang.Var.internPrivate(Var.java:149)
    at ca.gsimard.spacecraft.client.clojail.<clinit>(Unknown Source)
    at ca.gsimard.spacecraft.client.Epad$.eval(EpadClient.scala:78)
    at ca.gsimard.spacecraft.client.Main$.main(MainClient.scala:25)
    at ca.gsimard.spacecraft.client.Main.main(MainClient.scala)
[Loaded java.util.Objects from C:\Program Files\Java\jre7\lib\rt.jar]
Caused by: java.lang.NullPointerException
    at clojure.core$eval1697$fn__1698.invoke(core.clj:6135)
    at clojure.core$eval1697.invoke(core.clj:6135)
    at clojure.lang.Compiler.eval(Compiler.java:6465)
    at clojure.lang.Compiler.load(Compiler.java:6902)
    at clojure.lang.RT.loadResourceScript(RT.java:357)
    at clojure.lang.RT.loadResourceScript(RT.java:348)
    at clojure.lang.RT.load(RT.java:427)
    at clojure.lang.RT.load(RT.java:398)
    at clojure.lang.RT.doInit(RT.java:434)
    at clojure.lang.RT.<clinit>(RT.java:316)
    ... 7 more
[Loaded java.lang.Shutdown from C:\Program Files\Java\jre7\lib\rt.jar]
[Loaded java.lang.Shutdown$Lock from C:\Program Files\Java\jre7\lib\rt.jar]

Прежде чем кто-либо спросит, да, в этом приложении есть несколько потоков (использующих Akka Actors), и да, вызов epadEval выполняется из функции receive такого актера. ПК под управлением Windows 7 (где происходит сбой) имеет больше ядер, чем мой 2-ядерный ноутбук под управлением Linux (где этот сбой не происходит). Я предполагаю, что мне просто постоянно везет с нитями на моем ноутбуке.

  • Имеет ли это предположение смысл?
  • Как я могу убедиться, что класс clojail полностью загружен, прежде чем какой-либо поток попытается вызвать одну из его статических функций?

Ответы [ 3 ]

2 голосов
/ 26 марта 2012

Как отмечалось в другом ответе, это почти наверняка отличия среды.

Запуск java в подробном режиме, подобный следующему:

java -verbose -jar project.jar

даст много информации о загрузке классов.Если вам повезет, вы сможете получить некоторую полезную информацию о том, какие классы загружались непосредственно перед тем, как произошло исключение.

0 голосов
/ 29 марта 2012

Akka использует загрузчик классов контекста текущего потока (потока, создающего ActorSystem) (если есть). Может ли это играть здесь?

0 голосов
/ 26 марта 2012

99% времени эти проблемы возникают из-за различий в окружающей среде от одной машины к другой. Вы не упоминаете IDE (если есть - это Eclipse?)

Проверка ваших версий JVM и уверенность в том, что вы используете JVM, как вы думаете, важны. Например, вы можете использовать openJDK в Linux и Oracle JDK в Windows. Запустите java --version на обеих машинах, чтобы проверить вашу конфигурацию.

Пожалуйста, опубликуйте больше информации о вашей конфигурации, чтобы мы могли помочь вам в дальнейшем.

...