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

yeg*_*256 7 java clojure

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

import clojure.lang.Compiler;
Compiler.load(new StringReader("(+ 5 6)"));
Run Code Online (Sandbox Code Playgroud)

运行时异常:

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)
Run Code Online (Sandbox Code Playgroud)

看起来RT和Compiler类静态地互相引用.我正在使用org.clojure:clojure:1.5.0依赖.

Ale*_*lex 9

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

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

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

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