2013-03-04 20 views
6

我已在CLJ-1172中报告过此问题,但未收到来自Clojure团队的任何反馈。也许有人在这里可以告诉我什么是错的。这是我的代码:尝试加载资源时clojure.lang.Compiler中的NPE

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依赖项。

回答

8

只要这些类的字段按照正确的顺序初始化,就可以静态相互引用了。在这种情况下,Clojure可能会预计RTCompiler之前被初始化。以下是事件序列:

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

底线:使RT一些静态方法的调用(或读取静态字段),您的电话之前,Compiler.load和你的错误应该消失。

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

+0

你是对的,调用'RT.init()'事先解决了这个问题,谢谢! – yegor256 2013-03-05 06:03:40