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 はおそらく のRT前に初期化されることを想定していますCompiler。イベントのシーケンスは次のとおりです。

  1. を静的に呼び出すとCompiler、Java はそのクラスのすべての静的フィールドを初期化します。
  2. Compiler.FNONCE(行 47)の静的初期化子は、 の静的メソッドを呼び出します。これにより、 の値が計算されて設定されるRT前に、そのクラス全体が初期化されます。FNONCE
  3. 299 行目で始まる静的初期化ブロックは、最終的に静的フィールドRTを参照する静的メソッドを呼び出します。Compiler.LOADER
  4. JVM は通常、Compilerここでクラスを初期化しCompilerますが、現在初期化中であることを認識し、現在の値を取得します。フィールドは、ファイルで宣言されている順序で初期化され、 の初期化されていない値が返されたLOADER後に来るため、 で逆参照されると NPE がスローされます。FNONCEnullRT

結論: を呼び出すRT前に静的メソッドを呼び出す (または静的フィールドを読み取る)Compiler.loadと、エラーが解消されます。

クラスの初期化の詳細については、Java 言語仕様のセクション 12.4 を参照してください。

于 2013-03-04T23:59:27.520 に答える