2013-03-04 43 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