Issue with JavaFX and Jigsaw

Kevin Rushforth kevin.rushforth at oracle.com
Fri Apr 28 22:17:29 UTC 2017


Following up on this thread...

While writing the unit tests and documentation for this it became clear 
to me that it requiring applications to export as public API all 
packages used by FXML, Java Beans, and JavaScript callbacks from WebView 
is not a reasonable requirement.

The fact that we use sun.misc.reflect.MethodUtil.invoke is an 
implementation detail that should not dictate our API specification. As 
such, I have been working on a proposed fix as opposed to just 
documenting the existing limitation and producing a more understandable 
error message.

The fix will allow applications to "open" their package to just the 
javafx.base module (for Java Beans), or the javafx.fxml module (for 
FXML), or the javafx.web module (for JavaScript callbacks). This will 
allow applications to keep their FXML controller, for example, in a 
non-pubilc package, which is as it should be since the FXML controller 
is in almost all cases an implementation detail of the application.

I have a fix that should be ready for review early next week. It will 
also have the more descriptive error message in case the package is not 
open to the javafx module in question.

-- Kevin



On Tue, 11 Apr 2017 at 01:36 Trisha Gee <trisha.gee at gmail.com> wrote:

> From a user/developer point of view, a more descriptive error message 
> would be a big help.  I was completely at a loss to understand why I 
> needed to unconditionally export my packages, I figured there was a 
> requirement from the JavaFX-side of things but it wasn't clear what it 
> was or why. A helpful error plus updated documentation would reduce 
> confusion.
>
> On Tue, 11 Apr 2017 at 01:54 Mandy Chung <mandy.chung at oracle.com 
> <mailto:mandy.chung at oracle.com>> wrote:
>
>     It may be useful to point to the javadoc where it specifies to
>     require the module to export the packages unconditionally.
>
>     It would be a good RFE to relax the exports to at least javafx.beans.
>
>     Mandy
>
>>     On Apr 10, 2017, at 3:56 PM, Kevin Rushforth
>>     <kevin.rushforth at oracle.com <mailto:kevin.rushforth at oracle.com>>
>>     wrote:
>>
>>     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.gee at gmail.com> <mailto:trisha.gee at 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\.m
>>>>     2\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
>>>>         
>>>       
>


More information about the jigsaw-dev mailing list