尝试加载资源时,在clojure.lang.Compiler中使用NPE

时间:2013-03-04 17:40:11

标签: java clojure

我已在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依赖。

1 个答案:

答案 0 :(得分:8)

只要字段按正确的顺序初始化,类就可以静态引用彼此。在这种情况下,Clojure可能希望在RT之前初始化Compiler。这是事件的顺序:

  1. 当您对Compiler进行静态调用时,Java会初始化该类中的所有静态字段。
  2. Compiler.FNONCE的静态初始化程序(第47行)调用RT中的静态方法,这会导致在计算和设置FNONCE的值之前初始化整个类。 / LI>
  3. 从第299行开始的RT的静态初始化程序块调用静态方法,该方法最终引用静态Compiler.LOADER字段。
  4. JVM通常会在此处初始化Compiler类,但它会看到Compiler当前正在初始化并且只是获取当前值。字段按照在文件中声明的顺序进行初始化,并且LOADERFNONCE返回null的未初始化值,在{{{}}中取消引用时抛出NPE 1}}。
  5. 底线:在致电RT之前,在RT(或读取静态字段)中调用某个静态方法,您的错误就会消失。

    有关类初始化细节的更多详细信息,请参见Java Language Specification的第12.4节。