自更新9-u175以来,java默认允许非法访问,因此允许所有旧的反射技巧。工作正常,除了涉及control.skin中的类(也许其他人也没有检查) - 要重现,运行下面的示例,单击按钮,看看访问是否成功,直到尝试访问的行ButtonSkin中的私有字段。 stacktrace:
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,带有java9补丁的eclipse-oxygen-R,项目中的访问规则设置为允许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());
}
答案 0 :(得分:8)
为防止意外依赖新API,非法访问仅授予Java 9之前存在的软件包 - 因此我认为com.sun.javafx.scene.control.behavior
是新的。
在他的mail with the revised proposal for --illegal-access
Mark Reinhold写道(强调我的):
--illegal-access=permit
此模式打开运行时映像中每个模块中的每个包 所有未命名模块中的代码,即类路径上的代码,如果是,则为 包存在于JDK 8 中。这实现了静态访问,即通过 通过平台编译的字节码和深度反射访问 各种反思API。
对任何此类包的第一次反射访问操作会导致a 发出警告,但在此之后没有发出警告。 此单一警告描述了如何启用进一步警告。
此模式将是JDK 9的默认模式。它将在a中删除 未来发布。