自更新9-u175以來,java默認允許非法訪問,因此允許所有舊的反射技巧。工作正常,除非涉及到control.skin中的類(也可能是其他人,沒有檢查) - 重現,運行下面的示例,單擊按鈕,看看如何訪問成功,直到嘗試訪問私有ButtonSkin中的字段。堆棧跟蹤: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)
我的背景:jdk9-u175,Eclipse的氧-R與補丁java9,在項目准入規則設置爲允許的JavaFX/**
的問題是:誰是罪魁禍首? FX,Eclipse,ea還是..?
的例子:
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());
}
我在9 + 178上重現了錯誤。的確,非常奇怪的錯誤! – ZhekaKozlov