Sorry for the delay in responding.
I added a simple test program to the JBS bug that shows the same
behavior as the application and also an evaluation of the bug.
The short version is that JavaFX beans is (mostly) working as expected,
except for the misleading exception message. In JDK 9 it is required
that any object that is reflected on by JavaFX beans, specifically the
items passed to TableView, which are accessed via a
PropertyValueFactory, will need to be in a package that is exported
unconditionally. In JDK 10 we can look into relaxing this requirement
such that the package only needs to be exported to javafx.beans.
I do think we need to make the exception message less confusing in JDK 9
and also document the requirement in the appropriate places (at least in
TableView and probably in a couple of javafx.beans.property.adapter
classes).
Comments?
-- Kevin
Mandy Chung wrote:
Hi Trisha,
Thanks for the report and stack trace. I created
https://bugs.openjdk.java.net/browse/JDK-8177566 for further
investigation.
Mandy
On Mar 24, 2017, at 2:34 PM, Trisha Gee <trisha....@gmail.com> wrote:
Hi,
I was chatting to Alex Buckley at DevoxxUS about my experiences migrating a
project to using Java 9 modules (specifically, this project:
https://github.com/trishagee/sense-nine) and mentioned some surprising
behaviour in a module that uses JavaFX. I've been asked to send the
details so people can take a look at it.
My module-info.java is here:
https://github.com/trishagee/sense-nine/blob/master/src/com.mechanitis.demo.sense.client/module-info.java
Note that I have to export two additional packages (mood and user), and I
did not expect (or really want) to. This is because I was getting this
error if I did not:
java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native
Method)
at
java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at
java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:547)
at
javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:482)
at
javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:381)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native
Method)
at
java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at
java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:547)
at
java.base/sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:912)
Caused by: java.lang.RuntimeException: Exception in Application start method
at
javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:982)
at
javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:200)
at java.base/java.lang.Thread.run(Thread.java:844)
Caused by: java.lang.RuntimeException: *java.lang.IllegalAccessException:
class sun.reflect.misc.Trampoline cannot access class
com.mechanitis.demo.sense.client.user.TwitterUser (in module
com.mechanitis.demo.sense.client) because module
com.mechanitis.demo.sense.client does not export
com.mechanitis.demo.sense.client.user to unnamed module @779d6cc6*
at
javafx.base/com.sun.javafx.property.PropertyReference.getProperty(PropertyReference.java:200)
at
javafx.controls/javafx.scene.control.cell.PropertyValueFactory.getCellDataReflectively(PropertyValueFactory.java:145)
at
javafx.controls/javafx.scene.control.cell.PropertyValueFactory.call(PropertyValueFactory.java:119)
at
javafx.controls/javafx.scene.control.cell.PropertyValueFactory.call(PropertyValueFactory.java:98)
at
javafx.controls/javafx.scene.control.TableColumn.getCellObservableValue(TableColumn.java:579)
at
javafx.controls/javafx.scene.control.TableColumn.getCellObservableValue(TableColumn.java:564)
at
javafx.controls/javafx.scene.control.TableCell.updateItem(TableCell.java:645)
at
javafx.controls/javafx.scene.control.TableCell.indexChanged(TableCell.java:468)
at
javafx.controls/javafx.scene.control.IndexedCell.updateIndex(IndexedCell.java:116)
at
javafx.controls/javafx.scene.control.skin.TableRowSkinBase.updateCells(TableRowSkinBase.java:534)
at
javafx.controls/javafx.scene.control.skin.TableRowSkinBase.<init>(TableRowSkinBase.java:159)
at
javafx.controls/javafx.scene.control.skin.TableRowSkin.<init>(TableRowSkin.java:89)
at
javafx.controls/javafx.scene.control.TableRow.createDefaultSkin(TableRow.java:212)
at
javafx.controls/javafx.scene.control.Control.doProcessCSS(Control.java:895)
at javafx.controls/javafx.scene.control.Control.access$000(Control.java:83)
at
javafx.controls/javafx.scene.control.Control$1.doProcessCSS(Control.java:89)
at
javafx.controls/com.sun.javafx.scene.control.ControlHelper.processCSSImpl(ControlHelper.java:67)
at
javafx.graphics/com.sun.javafx.scene.NodeHelper.processCSS(NodeHelper.java:147)
at javafx.graphics/javafx.scene.Node.processCSS(Node.java:9356)
at javafx.graphics/javafx.scene.Node.applyCss(Node.java:9443)
at
javafx.controls/javafx.scene.control.skin.VirtualFlow.setCellIndex(VirtualFlow.java:1697)
at
javafx.controls/javafx.scene.control.skin.VirtualFlow.getCell(VirtualFlow.java:1674)
at
javafx.controls/javafx.scene.control.skin.VirtualFlow.getCellLength(VirtualFlow.java:1781)
at
javafx.controls/javafx.scene.control.skin.VirtualFlow.computeViewportOffset(VirtualFlow.java:2618)
at
javafx.controls/javafx.scene.control.skin.VirtualFlow.layoutChildren(VirtualFlow.java:1242)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1226)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1233)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1233)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1233)
at javafx.graphics/javafx.scene.Scene.doLayoutPass(Scene.java:585)
at javafx.graphics/javafx.scene.Scene.preferredSize(Scene.java:1767)
at javafx.graphics/javafx.scene.Scene$2.preferredSize(Scene.java:389)
at
javafx.graphics/com.sun.javafx.scene.SceneHelper.preferredSize(SceneHelper.java:66)
at javafx.graphics/javafx.stage.Window$12.invalidated(Window.java:1092)
at
javafx.base/javafx.beans.property.BooleanPropertyBase.markInvalid(BooleanPropertyBase.java:110)
at
javafx.base/javafx.beans.property.BooleanPropertyBase.set(BooleanPropertyBase.java:145)
at javafx.graphics/javafx.stage.Window.setShowing(Window.java:1180)
at javafx.graphics/javafx.stage.Window.show(Window.java:1195)
at javafx.graphics/javafx.stage.Stage.show(Stage.java:267)
at
com.mechanitis.demo.sense.client/com.mechanitis.demo.sense.client.Dashboard.start(Dashboard.java:45)
at
javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(LauncherImpl.java:928)
at
javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runAndWait$11(PlatformImpl.java:449)
at
javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$9(PlatformImpl.java:418)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at
javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:417)
at
javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native
Method)
at
javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:189)
... 1 more
Caused by: java.lang.IllegalAccessException: class
sun.reflect.misc.Trampoline cannot access class
com.mechanitis.demo.sense.client.user.TwitterUser (in module
com.mechanitis.demo.sense.client) because module
com.mechanitis.demo.sense.client does not export
com.mechanitis.demo.sense.client.user to unnamed module @779d6cc6
at
java.base/jdk.internal.reflect.Reflection.throwIllegalAccessException(Reflection.java:423)
at
java.base/jdk.internal.reflect.Reflection.throwIllegalAccessException(Reflection.java:414)
at
java.base/jdk.internal.reflect.Reflection.ensureMemberAccess(Reflection.java:112)
at
java.base/java.lang.reflect.AccessibleObject.slowCheckMemberAccess(AccessibleObject.java:632)
at
java.base/java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:624)
at java.base/java.lang.reflect.Method.invoke(Method.java:539)
at sun.reflect.misc.Trampoline.invoke(MethodUtil.java:72)
at jdk.internal.reflect.GeneratedMethodAccessor2.invoke(Unknown Source)
at
java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:547)
at java.base/sun.reflect.misc.MethodUtil.invoke(MethodUtil.java:261)
at
javafx.base/com.sun.javafx.property.PropertyReference.getProperty(PropertyReference.java:198)
... 48 more
When I discovered this I was a bit stumped about what was in the unnamed
module, given this appears to be JavaFX code causing this.
I'm running this from inside IntelliJ IDEA, this is the command it's
calling: "C:\Program Files\Java\jdk-9\bin\java"
-Djava.util.logging.config.file=logging.properties
-javaagent:C:\Users\Trisha\AppData\Local\JetBrains\Toolbox\apps\IDEA-U\ch-0\171.3780.107\lib\idea_rt.jar=54310:C:\Users\Trisha\AppData\Local\JetBrains\Toolbox\apps\IDEA-U\ch-0\171.3780.107\bin
-Dfile.encoding=UTF-8 -p
C:\Users\Trisha\Projects\trishagee\sense-nine\out\production\com.mechanitis.demo.sense.client;C:\Users\Trisha\Projects\trishagee\sense-nine\out\production\com.mechanitis.demo.sense.service;C:\Users\Trisha\.m2\repository\org\eclipse\jetty\websocket\javax-websocket-server-impl\9.4.1.v20170120\javax-websocket-server-impl-9.4.1.v20170120.jar;C:\Users\Trisha\.m2\repository\org\eclipse\jetty\jetty-annotations\9.4.1.v20170120\jetty-annotations-9.4.1.v20170120.jar;C:\Users\Trisha\.m2\repository\org\eclipse\jetty\jetty-plus\9.4.1.v20170120\jetty-plus-9.4.1.v20170120.jar;C:\Users\Trisha\.m2\repository\org\eclipse\jetty\jetty-webapp\9.4.1.v20170120\jetty-webapp-9.4.1.v20170120.jar;C:\Users\Trisha\.m2\repository\org\eclipse\jetty\jetty-xml\9.4.1.v20170120\jetty-xml-9.4.1.v20170120.jar;C:\Users\Trisha\.m2\repository\org\eclipse\jetty\jetty-util\9.4.1.v20170120\jetty-util-9.4.1.v20170120.jar;C:\Users\Trisha\.m2\repository\org\eclipse\jetty\jetty-servlet\9.4.1.v20170120\jetty-servlet-9.4.1.v20170120.jar;C:\Users\Trisha\.m2\repository\org\eclipse\jetty\jetty-security\9.4.1.v20170120\jetty-security-9.4.1.v20170120.jar;C:\Users\Trisha\.m2\repository\org\eclipse\jetty\jetty-server\9.4.1.v20170120\jetty-server-9.4.1.v20170120.jar;C:\Users\Trisha\.m2\repository\javax\servlet\javax.servlet-api\3.1.0\javax.servlet-api-3.1.0.jar;C:\Users\Trisha\.m2\repository\org\eclipse\jetty\jetty-http\9.4.1.v20170120\jetty-http-9.4.1.v20170120.jar;C:\Users\Trisha\.m2\repository\org\eclipse\jetty\jetty-io\9.4.1.v20170120\jetty-io-9.4.1.v20170120.jar;C:\Users\Trisha\.m2\repository\org\eclipse\jetty\jetty-jndi\9.4.1.v20170120\jetty-jndi-9.4.1.v20170120.jar;C:\Users\Trisha\.m2\repository\javax\annotation\javax.annotation-api\1.2\javax.annotation-api-1.2.jar;C:\Users\Trisha\.m2\repository\org\ow2\asm\asm\5.1\asm-5.1.jar;C:\Users\Trisha\.m2\repository\org\ow2\asm\asm-commons\5.1\asm-commons-5.1.jar;C:\Users\Trisha\.m2\repository\org\ow2\asm\asm-tree\5.1\asm-tree-5.1.jar;C:\Users\Trisha\.m2\repository\org\eclipse\jetty\websocket\javax-websocket-client-impl\9.4.1.v20170120\javax-websocket-client-impl-9.4.1.v20170120.jar;C:\Users\Trisha\.m2\repository\org\eclipse\jetty\websocket\websocket-client\9.4.1.v20170120\websocket-client-9.4.1.v20170120.jar;C:\Users\Trisha\.m2\repository\org\eclipse\jetty\jetty-client\9.4.1.v20170120\jetty-client-9.4.1.v20170120.jar;C:\Users\Trisha\.m2\repository\org\eclipse\jetty\websocket\websocket-common\9.4.1.v20170120\websocket-common-9.4.1.v20170120.jar;C:\Users\Trisha\.m2\repository\org\eclipse\jetty\websocket\websocket-api\9.4.1.v20170120\websocket-api-9.4.1.v20170120.jar;C:\Users\Trisha\.m2\repository\javax\websocket\javax.websocket-api\1.0\javax.websocket-api-1.0.jar;C:\Users\Trisha\.m2\repository\org\eclipse\jetty\websocket\websocket-server\9.4.1.v20170120\websocket-server-9.4.1.v20170120.jar;C:\Users\Trisha\.m2\repository\org\eclipse\jetty\websocket\websocket-servlet\9.4.1.v20170120\websocket-servlet-9.4.1.v20170120.jar
-m
com.mechanitis.demo.sense.client/com.mechanitis.demo.sense.client.Dashboard
Thanks,
Trisha