2013-03-04 27 views
6

Tôi đã báo cáo sự cố này trong CLJ-1172, nhưng không nhận được bất kỳ phản hồi nào từ nhóm Clojure. Có lẽ ai đó ở đây có thể cho tôi biết có gì sai. Đây là mã của tôi:NPE trong clojure.lang.Compiler khi cố tải tài nguyên

import clojure.lang.Compiler; 
Compiler.load(new StringReader("(+ 5 6)")); 

ngoại lệ trong thời gian chạy:

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) 

Hình như RTCompiler lớp tĩnh tham khảo lẫn nhau. Tôi đang sử dụng phụ thuộc org.clojure:clojure:1.5.0.

Trả lời

8

OK để các lớp tham chiếu tĩnh với nhau miễn là các trường của chúng được khởi tạo theo đúng thứ tự. Trong trường hợp này, Clojure có thể mong đợi RT được khởi tạo trước Compiler. Đây là chuỗi sự kiện:

  1. Khi bạn thực hiện cuộc gọi tĩnh đến Compiler, Java sẽ khởi tạo tất cả các trường tĩnh trong lớp đó.
  2. Trình khởi tạo tĩnh cho Compiler.FNONCE (dòng 47) gọi phương thức tĩnh trong RT, làm cho toàn bộ lớp được khởi tạo trước khi giá trị của FNONCE được tính toán và thiết lập.
  3. Khối khởi tạo tĩnh cho RT bắt đầu trên dòng 299 gọi phương thức tĩnh mà cuối cùng đề cập đến trường tĩnh Compiler.LOADER.
  4. JVM thường khởi tạo lớp Compiler tại đây, nhưng nó thấy rằng Compiler hiện đang được khởi tạo và chỉ lấy giá trị hiện tại. Các trường được khởi tạo theo thứ tự chúng được khai báo trong tệp và kể từ LOADER xuất hiện sau FNONCE giá trị chưa được khởi tạo của null được trả về, ném một NPE khi nó bị hủy tham chiếu trong RT.

Dòng dưới cùng: thực hiện cuộc gọi đến một số phương pháp tĩnh trong RT (hoặc đọc trường tĩnh) trước khi gọi tới Compiler.load và lỗi của bạn sẽ biến mất.

Thêm chi tiết về chi tiết cụ thể về khởi tạo lớp có sẵn trong phần 12.4 của Java Language Specification.

+0

bạn nói đúng, gọi 'RT.init() 'trước đó giải quyết được vấn đề, cảm ơn! – yegor256

Các vấn đề liên quan