Scala/Clojure互操作在PC上可以工作,但在另一台电脑上失败,出现java.lang.ExceptionInI



我有一个用Java/Scala混合语言编写的项目,在这个项目中,我调用了一个由Clojure生成的类(ca.gsimard.spacer.client.clojail)公开的静态方法(epadEval)。

在监狱里。clj:
(与Leinengen一起编译成一个独立的罐子:"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项目中,我导入了之前由Leinengen生成的.jar):

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

我通过构建一个胖罐子来部署这个项目并运行它:

在PC1(Linux)上:

Epad: 6

在PC2(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类甚至没有被加载。在(ns..)和(defn...)之间添加(println..)命令根本不会在PC2上打印任何内容,所以问题似乎出在加载时,而不是调用时。

请注意,在失败的同一台Windows7计算机上,我可以通过调用(-epadEval..)的(-main)方法成功构建并运行一个仅限Clojure的独立uberjar。

知道这里发生了什么吗

编辑:我已经用java运行了这个-verbose,如下所示。据我所知,函数epadEval在定义之前就被调用了!JVM仍在加载clojure.core时发生异常。在此之前,我没有看到任何〔Loaded ca.gsimard.spacers.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 FilesJavajre7librt.jar]
[Loaded java.lang.Throwable$WrappedPrintStream from C:Program FilesJavajre7librt.jar]
[Loaded java.util.IdentityHashMap$KeySet from C:Program FilesJavajre7librt.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 FilesJavajre7librt.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 FilesJavajre7librt.jar]
[Loaded java.lang.Shutdown$Lock from C:Program FilesJavajre7librt.jar]

在有人问之前,是的,这个应用程序中有多个线程(使用Akka Actors),是的。对epadEval的调用是通过这样一个actor的receive函数完成的。运行Windows7的电脑(在崩溃的地方)比我运行Linux的2核笔记本电脑(在不崩溃的情况下)有更多的核。我的猜测是,我现在对笔记本电脑上的线程一直很幸运。

  • 这个猜测有意义吗
  • 在某个线程尝试调用其静态函数之前,如何确保clojail类已完全加载

正如另一个答案中所指出的,这几乎可以肯定是环境差异。

在详细模式下运行java,如下所示:

java -verbose -jar project.jar

将提供大量关于类加载的信息。如果运气好的话,您将能够推断出一些有用的信息,在异常发生之前,哪些类正在加载。

Akka使用当前线程(创建ActorSystem的线程)的上下文类加载器(如果有的话)。这能在这里演奏吗?

99%的情况下,这些问题是由于不同机器的环境差异造成的。你没有提到IDE(如果有的话——是Eclipse吗?)

检查JVM版本并确保您使用的是您认为的JVM是很重要的。例如,您可以在Linux上使用openJDK,在Windows上使用OracleJDK。在两台机器上运行java-version来检查您的配置。

请发布有关您的配置的更多信息,以便我们能够提供进一步帮助。

相关内容

最新更新