eclipse - Deep reflection fails in xxSkin classes -
since update 9-u175, java permits illegal access default allowing old reflection tricks. works fine, except when comes classes in control.skin (maybe others well, didn't check) - reproduce, run example below, click button , see how access succeeds until line tries access private field in buttonskin. stacktrace:
exception in thread "javafx application thread" java.lang.reflect.inaccessibleobjectexception: unable make field private final com.sun.javafx.scene.control.behavior.behaviorbase javafx.scene.control.skin.buttonskin.behavior accessible: module javafx.controls not "opens javafx.scene.control.skin" unnamed module @537fb2 @ java.base/java.lang.reflect.accessibleobject.checkcansetaccessible(accessibleobject.java:337) @ java.base/java.lang.reflect.accessibleobject.checkcansetaccessible(accessibleobject.java:281) @ java.base/java.lang.reflect.field.checkcansetaccessible(field.java:176) @ java.base/java.lang.reflect.field.setaccessible(field.java:170)
my context: jdk9-u175, eclipse-oxygen-r patch java9, access rules in project set allow javafx/**
the question is: who's culprit? fx, eclipse, ea or ..?
the example:
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 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()); }
to prevent accidental dependencies on new apis, illegal access granted packages existed before java 9 - hence assume com.sun.javafx.scene.control.behavior
new.
in mail revised proposal --illegal-access
mark reinhold writes (emphasis mine):
--illegal-access=permit
this mode opens each package in each module in run-time image code in unnamed modules, i.e., code on class path, if package existed in jdk 8. enables both static access, i.e., compiled bytecode, , deep reflective access, via platform's various reflection apis.
the first reflective-access operation such package causes warning issued, no warnings issued after point. single warning describes how enable further warnings.
this mode default jdk 9. removed in future release.
Comments
Post a Comment