2017-01-24 17 views
5

Tôi đang sử dụng jdk-9 và tôi muốn sử dụng sun.reflect.* gói trong mã của tôi, nhưng tôi nhận được ngoại lệ bên dướiCách sử dụng gói sun.reflect trong jdk9/java-9?

Exception in thread 'main' java.lang.IllegalAccessError : class Test (in moudle: Unnamed Module) cannot access class sun.reflect.Reflaction (in module:java.base), sun.reflect is not exported to Unnamed module 

khi tôi chạy bên dưới mẫu mã sử dụng JDK-9

public static void main(String args[]){ 
    System.out.println(Reflection.getCallerClass(3)); 
} 

Trả lời

3
java -cp classes -XaddExports:java.base/sun.reflect Test 

Ghép hình (java-9) có khái niệm mô đun, trong đó chúng đã thiết kế gói java.base cho compact-1 và chúng đã đóng gói sun.reflect.*. do đó, không thể truy cập vào sun.reflect.* bên ngoài. Do lý do đó, việc đưa ra ngoại lệ

Exception in thread 'main' java.lang.IllegalAccessError : class Test (in moudle: Unnamed Module) cannot access class sun.reflect.Reflaction (in module:java.base), sun.reflect is not exported to Unnamed module 

Vẫn cung cấp khả năng tương thích ngược, họ đã cung cấp cách sử dụng gói đó như dưới đây.

java -cp classes -XaddExports:java.base/sun.reflect Test 
+3

Câu trả lời có phần gây hiểu lầm: (1) cấu hình nhỏ gọn không liên quan gì đến nó; (2) nó cũng không thành công đối với tất cả các loại gói khác; (3) thông báo lỗi và giải pháp đề xuất đã lỗi thời. Xem [my answer] (http://stackoverflow.com/a/41824999/2525313) để thay thế. – Nicolai

+1

@Nicolai Câu trả lời của bạn đã lỗi thời. Xem [câu trả lời này] (http://stackoverflow.com/a/42187227/706317) thay vào đó :) – ZhekaKozlov

5

ĐÁP này đã lỗi thời - KIỂM TRA THIS ONE THAY!

Tính năng của hệ thống mô-đun là nó cho phép nhà phát triển thư viện đóng gói mạnh mẽ chi tiết triển khai do accessibility rules mới. Tóm lại, hầu hết các loại trong các gói sun.*com.sun.* sẽ không thể truy cập được nữa. Điều này là phù hợp với Sun và sau đó Oracle nói rằng các gói này không có nghĩa là để tiêu thụ công cộng.

Một cách giải quyết là để xuất khẩu những gói tại biên dịch và khởi động thời gian với một cờ dòng lệnh:

--add-exports java.base/sun.reflect=ALL-UNNAMED 

này xuất khẩu các gói sun.reflect từ các module java.base để tất cả các module bao gồm unnamed module, mà là một trong đó thu thập tất cả các lớp trên đường dẫn lớp.

+0

Điều này tôi nghĩ nên là '--thêm xuất khẩu jdk.unsupported/sun.reflect = ALL-UNNAMED' – reversiblean

4

Các gói sun.* này không bao giờ là một phần của API chính thức và không được bảo đảm hiện diện, ngay cả trong các JVM trước Java 9. Hãy chuẩn bị cho chúng biến mất hoàn toàn trong tương lai, thậm chí không thể khôi phục được qua một số tùy chọn. Rất may, có một API chính thức bao gồm chức năng này, loại bỏ sự cần thiết cho các API không chính thức.

Lấy lớp người gọi ngay lập tức
Class<?> c = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE) 
         .getCallerClass(); 
Lấy gọi n'th trên stack (ví dụ thứ ba, như trong ví dụ của bạn):
Class<?> c = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE).walk(s -> 
    s.map(StackWalker.StackFrame::getDeclaringClass).skip(3).findFirst().orElse(null)); 
6

Hoạt động tốt với phiên bản mới hơn OpenJDK 9 EA xây dựng. Ví dụ:

$ java -version 
java version "9-ea" 
Java(TM) SE Runtime Environment (build 9-ea+138) 
Java HotSpot(TM) 64-Bit Server VM (build 9-ea+138, mixed mode) 

$ javac Test.java 
Test.java:5: warning: Reflection is internal proprietary API and may be removed in a future release 
    System.out.println(Reflection.getCallerClass(3)); 
        ^
Note: Test.java uses or overrides a deprecated API. 
Note: Recompile with -Xlint:deprecation for details. 
1 warning 

$ java Test 
null 

Có vẻ như nó đã được sửa trong 9-ea + 115 như một phần của JDK-8137058. Vì vậy, có lẽ bạn đang sử dụng EA build cũ hơn. Nói chung @Holger là đúng: có nhiều cơ hội mà API này sẽ biến mất hoàn toàn trong các phiên bản Java trong tương lai, vì vậy hãy xem xét di chuyển sang StackWalker API.

+2

Thật vậy, 'sun.reflect.Reflection' đã chuyển sang mô-đun' jdk.unsupported'. Vì vậy, nó sẽ có ít nhất cho đến khi Java 10. – ZhekaKozlov

1

Cập nhật chuỗi với bản phát hành mới nhất và thay đổi được đưa vào như được đề cập trong số Migration documentation. Một cách thích hợp một cách chính xác pointed out by @Holger đã được mặc dù.

Các API trong sun.reflect gói mà vẫn truy cập được trong JDK 9 là:

  • sun.reflect.Reflection::getCallerClass(int) Thay vào đó, sử dụng API stack-đi bộ, xem JEP 259: Stack-Walking API.
  • sun.reflect.ReflectionFactory.newConstructorForSerialization

Các API này có thể truy cập lại theo mặc định vào thời gian chạy. Chúng đã được chuyển sang mô-đun jdk.unsupported, có trong hình ảnh JRE và JDK. Các mô-đun cần các API này phải khai báo sự phụ thuộc vào mô-đun jdk.unsupported.

Các API nội bộ còn lại trong gói sun.misc và sun.reflect đã bị di chuyển vì chúng không thể truy cập được. Nếu bạn cần sử dụng một trong các API nội bộ này, bạn có thể ngắt đóng gói bằng cách sử dụng tùy chọn dòng lệnh --add-exports. (tương tự như answered by @NIrav). Mặc dù như được đề xuất trong tài liệu, tùy chọn này chỉ nên được sử dụng làm trợ giúp tạm thời cho việc di chuyển.

+0

Nếu bạn chưa quen với các mô-đun java9, nó sẽ hữu ích khi biết rằng bạn phải thêm một tệp mới vào gói của bạn, được gọi là module-info.java, khai báo sự phụ thuộc vào jdk.unsupported. nó trông như thế này: 'module com.mypackage {yêu cầu jdk.unsupported; yêu cầu org.apache.logging.log4j; xuất khẩu com.mypackage; } ' – BrettonW

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