7

我已经在CLJ-1172中报告了这个问题,但没有收到 Clojure 团队的任何反馈。也许这里有人可以告诉我出了什么问题。这是我的代码:

import clojure.lang.Compiler;
Compiler.load(new StringReader("(+ 5 6)"));

运行时异常:

java.lang.ExceptionInInitializerError
  at clojure.lang.Compiler.<clinit>(Compiler.java:47)
Caused by: java.lang.NullPointerException
  at clojure.lang.RT.baseLoader(RT.java:2043)
  at clojure.lang.RT.load(RT.java:417)
  at clojure.lang.RT.load(RT.java:411)
  at clojure.lang.RT.doInit(RT.java:447)
  at clojure.lang.RT.<clinit>(RT.java:329)

看起来RTCompiler类静态地相互引用。我正在使用org.clojure:clojure:1.5.0依赖项。

4

1 回答 1

9

只要它们的字段以正确的顺序初始化,类就可以静态地相互引用。在这种情况下,Clojure 可能期望RTCompiler. 以下是事件的顺序:

  1. 当您对 进行静态调用时Compiler,Java 会初始化该类中的所有静态字段。
  2. (第 47 行)的静态初始化程序Compiler.FNONCE调用 in 中的静态方法,这会导致整个类在计算和设置RT的值之前被初始化。FNONCE
  3. 从第 299 行开始的静态初始化程序块RT调用一个静态方法,该方法最终引用静态Compiler.LOADER字段。
  4. JVM 通常会在Compiler此处初始化该类,但它看到Compiler当前正在初始化并仅获取当前值。字段按照它们在文件中声明的顺序进行初始化,并且由于LOADER在返回FNONCE未初始化的值之后null,当它被取消引用时抛出一个 NPE RT

底线:在调用RT之前调用(或读取静态字段)中的某些静态方法,Compiler.load并且您的错误应该消失。

有关类初始化细节的更多详细信息,请参见Java 语言规范的第 12.4 节。

于 2013-03-04T23:59:27.520 回答