2017-07-28 11 views
7

Kể từ khi cập nhật 9-u175, java cho phép truy cập trái phép theo mặc định, cho phép tất cả các thủ thuật phản chiếu cũ. Hoạt động tốt, ngoại trừ khi nói đến các lớp trong control.skin (có thể những người khác nữa, không kiểm tra) - để tái sản xuất, chạy ví dụ bên dưới, nhấp vào nút và xem cách truy cập thành công cho đến khi dòng cố truy cập riêng tư trong trường ButtonSkin. Stacktrace:Phản chiếu sâu không thành công trong các lớp xxSkin

Exception in thread "JavaFX Application Thread" java.lang.reflect.InaccessibleObjectException: 
Unable to make field private final com.sun.javafx.scene.control.behavior.BehaviorBase javafx.scene.control.skin.ButtonSkin.behavior accessible: 
module javafx.controls does not "opens javafx.scene.control.skin" to unnamed module @537fb2 
    at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:337) 
    at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:281) 
    at java.base/java.lang.reflect.Field.checkCanSetAccessible(Field.java:176) 
    at java.base/java.lang.reflect.Field.setAccessible(Field.java:170) 

My bối cảnh: jdk9-u175, nhật thực-oxy-R với bản vá cho java9, các quy tắc truy cập trong dự án được thiết lập để cho phép JavaFX/**

Câu hỏi đặt ra là: ai là thủ phạm? FX, Eclipse, ea hoặc ..?

Ví dụ:

import java.lang.reflect.Field; 
import java.util.logging.Logger; 

import javafx.application.Application; 
import javafx.scene.Parent; 
import javafx.scene.Scene; 
import javafx.scene.control.Button; 
import javafx.scene.control.SkinBase; 
import javafx.scene.control.skin.ButtonSkin; 
import javafx.scene.layout.BorderPane; 
import javafx.stage.Stage; 
import com.sun.javafx.scene.control.LambdaMultiplePropertyChangeListenerHandler; 

public class AccessFieldFX extends Application { 

    private Parent getContent() { 
     Button button = new Button("something to click on"); 
     // okay 
     Object def = invokeGetFieldValue(Button.class, button, "defaultButton"); 

     button.setOnAction(e -> { 
      ButtonSkin skin = (ButtonSkin) button.getSkin(); 
      // okay 
      LambdaMultiplePropertyChangeListenerHandler cl = 
        (LambdaMultiplePropertyChangeListenerHandler) invokeGetFieldValue(SkinBase.class, skin, "lambdaChangeListenerHandler"); 
      // okay 
      Object clField = invokeGetFieldValue(LambdaMultiplePropertyChangeListenerHandler.class, cl, "EMPTY_CONSUMER"); 
      // failure 
      Object beh = invokeGetFieldValue(ButtonSkin.class, skin, "behavior"); 
     }); 
     BorderPane pane = new BorderPane(button); 
     return pane; 
    } 

    @Override 
    public void start(Stage primaryStage) throws Exception { 
     primaryStage.setScene(new Scene(getContent(), 600, 400)); 
//  primaryStage.setTitle(FXUtils.version()); 
     primaryStage.show(); 
    } 

    public static Object invokeGetFieldValue(Class declaringClass, Object target, String name) { 
     try { 
      Field field = declaringClass.getDeclaredField(name); 
      field.setAccessible(true); 
      return field.get(target); 
     } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) { 
      e.printStackTrace(); 
     } 
     return null; 
    } 

    public static void main(String[] args) { 
     launch(args); 
    } 

    @SuppressWarnings("unused") 
    private static final Logger LOG = Logger 
      .getLogger(AccessFieldFX.class.getName()); 
} 
+0

Tôi đã sao chép lỗi trên 9 + 178. Thật vậy, lỗi rất lạ! – ZhekaKozlov

Trả lời

8

Để tránh phụ thuộc tình cờ trên các API mới, truy cập bất hợp pháp chỉ được cấp cho các gói đã tồn tại trước Java 9 - Tôi vì thế giả com.sun.javafx.scene.control.behavior phải là mới.

Trong mail with the revised proposal for --illegal-access Đánh dấu Reinhold mình viết (tôi nhấn mạnh):

--illegal-access=permit

chế độ này mở từng gói trong mỗi module trong hình ảnh thời gian chạy để mã trong tất cả các module giấu tên, ví dụ, mã trên đường dẫn lớp học, nếu gói đó tồn tại trong JDK 8. Điều này cho phép cả truy cập tĩnh, tức là, bằng bytecode được biên dịch và truy cập phản xạ sâu, thông qua các API phản chiếu khác nhau của nền tảng .

Thao tác truy cập phản chiếu đầu tiên đối với bất kỳ gói nào như vậy sẽ gây ra cảnh báo , nhưng không có cảnh báo nào được phát hành sau thời điểm đó. Cảnh báo đơn này mô tả cách bật cảnh báo thêm.

Chế độ này sẽ là mặc định cho JDK 9. Nó sẽ bị xóa trong bản phát hành tương lai .

+2

đó là nó: javafx.scene.control.skin là mới trong java9 (di chuyển từ comi comi nội bộ ... thành công khai) Vì vậy, chúng ta cần -add-mở ... của gói da bây giờ và trong tương lai. Cảm ơn! – kleopatra

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