Illegal Reflective Operation

174 views
Skip to first unread message

Brad Grier

unread,
Apr 20, 2018, 4:31:02 PM4/20/18
to mozilla-rhino
I get this output whenever I run my project in Java 9 or 10. Is this going to be an issue going forward?

WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by org.mozilla.javascript.MemberBox (file:/home/me/dev/photogrok/rhino-1.7.7.2.jar) to method sun.java2d.SunGraphics2D.drawImage(java.awt.Image,int,int,java.awt.image.ImageObserver)
WARNING: Please consider reporting this to the maintainers of org.mozilla.javascript.MemberBox
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release

Gregory Brail

unread,
Apr 20, 2018, 4:51:05 PM4/20/18
to mozill...@googlegroups.com
From what I read, this is a new warning introduced with the Java 9 module system to discourage projects from bypassing the public interface of a module and calling directly in to internal classes.

I don't see anywhere in Rhino where the code calls that method, or uses the SunGraphics2D class.

Does your Rhino-based app have some code that uses that class?



--
You received this message because you are subscribed to the Google Groups "mozilla-rhino" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mozilla-rhin...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Brad Grier

unread,
Apr 20, 2018, 6:11:34 PM4/20/18
to mozilla-rhino
Yes. The software is available at: http://www.metaloupe.com. It's a photo utility that (among other things) allows users to write their own scripts to interface with the app. This includes creating custom image filters in JavaScript. One or more of my scripts is triggering this message. The program allows users to optionally use Nashorn or Rhino (and maybe someday Detroit) so it wouldn't be a show-stopper if a future JDK turned off this "illegal access". Nevertheless, I like having the option to use Rhino.

Gregory Brail

unread,
Apr 25, 2018, 12:34:49 PM4/25/18
to mozill...@googlegroups.com
Thanks.

Rhino just calls the Java methods that the caller gives it, using reflection so that's what's available. There's really nothing that we can do about this warning in Rhino itself, because the root cause is that the JavaScript code that Metaloupe is running is using these internal JVM classes.

I would imagine that other JavaScript engines, and in fact pretty much any software that runs this product on Java 9 would have this problem.

The only fix I'm aware of is for Metaloupe to stop depending on that internal "sun.java2d" class and use the public interface to SunGraphics2D instead.
Message has been deleted

Brad Grier

unread,
Apr 25, 2018, 3:46:15 PM4/25/18
to mozilla-rhino
Below is a very simple "painter" that throws a warning in Rhino but works fine in Nashorn. In this case, I get the following: WARNING: Illegal reflective access by org.mozilla.javascript.MemberBox (file:/home/brad/dev/photogrok/rhino-1.7.7.2.jar) to method sun.java2d.SunGraphics2D.setColor(java.awt.Color)

// @scriptengine rhino

var painter = function(gfx, image, fullImage, props){

// draw the file name on the image
gfx.setColor(Color.RED);
gfx.drawString(props.file, 20, 50);

};

setPainter(painter);


I'm not sure why it's using sun.java2d.SunGraphics2D. I don't reference that class at all in Java. The parameter to the paint method in the Painter interface is defined as java.awt.Graphics2D.

Thanks.

Michael Hall

unread,
Apr 25, 2018, 4:23:33 PM4/25/18
to mozill...@googlegroups.com

> On Apr 25, 2018, at 2:46 PM, Brad Grier <bradm...@gmail.com> wrote:
>
> Below is a very simple "painter" that throws a warning in Rhino but works fine in Nashorn. In this case, I get the following: WARNING: Illegal reflective access by org.mozilla.javascript.MemberBox (file:/home/brad/dev/photogrok/rhino-1.7.7.2.jar) to method sun.java2d.SunGraphics2D.setColor(java.awt.Color)
>

I think this might be off-track as far as what is wrong. It’s not that Rhino is directly using the prohibited ‘sun’ internal, although it appears something is, directly or indirectly.

This shows Rhino doesn’t do so directly.

jdeps -jdkinternals ~/Downloads/rhino1.7.7.2/lib/rhino-1.7.7.2.jar

returns nothing. So Rhino is clear there.

The message I think comes from…
> org.mozilla.javascript.MemberBox

including

import java.lang.reflect.*;

At some point in time use of reflection is going to be somewhat restricted. Something is using this class - MemberBox - to do reflection, probably to something that in turn uses the prohibited ‘sun’ class so the jeeps command doesn’t catch it.
This is just a warning message that at some point the reflection that MemberBox is doing will not be allowed.

The code that is using the ‘sun’ class, wherever it is, should be broke now though? You might use the jdeps command on the other jars you include to see if any of them flag it.



Brad Grier

unread,
Apr 25, 2018, 5:20:48 PM4/25/18
to mozilla-rhino
Nothing appears to be broken. The code I posted works but outputs the reflection warning only when using Rhino. I ran jdeps against every jar file used in the program. I don't see anything referencing sun.java2d.SunGraphics2D although my application jar and the look and feel jar both access com.sun.awt.AWTUtilities - I think to display rounded corners on swing windows and dialogs. That said, the MemberBox warning is only generated when a photo is displayed in the app and the registered javascript "painter" is called. No warning is ever generated when using Nashorn to run the same script.

Michael Hall

unread,
Apr 25, 2018, 5:25:59 PM4/25/18
to mozill...@googlegroups.com

On Apr 25, 2018, at 4:20 PM, Brad Grier <bradm...@gmail.com> wrote:

Nothing appears to be broken. The code I posted works but outputs the reflection warning only when using Rhino. I ran jdeps against every jar file used in the program. I don't see anything referencing sun.java2d.SunGraphics2D although my application jar and the look and feel jar both access com.sun.awt.AWTUtilities - I think to display rounded corners on swing windows and dialogs. That said, the MemberBox warning is only generated when a photo is displayed in the app and the registered javascript "painter" is called. No warning is ever generated when using Nashorn to run the same script.

The warning I would still guess comes from 
org.mozilla.javascript.MemberBox 

which would be Rhino specific? I guess I have no idea where the ‘sun’ class is getting hit from if it is not in any of your jars. Possibly validly through a core java class which you said use? Then Rhino will just need to address the reflection concerns at some point before that becomes an actual error.

Gregory Brail

unread,
Apr 26, 2018, 12:59:35 PM4/26/18
to mozill...@googlegroups.com
This is indeed strange. Assuming that Rhino is just using reflection to access java.awt.Graphics2D.setColor, then that shouldn't 

Apparently if you pass the JVM flag:

--illegal-access=debug

then you can get a stack trace. Perhaps that would help? 

And are you sure that "gfx" is a java.awt.Graphics2D and not something else?

Sorry, having trouble understanding why we'd get an error in this particular case and not in all the other places where Rhino uses reflection.

Brad Grier

unread,
Apr 26, 2018, 2:26:42 PM4/26/18
to mozilla-rhino
Yes, it's curious. Thanks for taking time to look at this. Here are the relevant Java bits. First the painter interface:

package photogrok;

import java.awt.Graphics2D;
import java.awt.image.BufferedImage;

public interface Painter {

    public void paint(Graphics2D g, BufferedImage scaledImage, BufferedImage origImage, PainterProps pp);
}

Here's the Java call to the painter implementation (created and registered from javascript - see painter code in previous reply). I verified the Graphics2D imported in the class and used for the first parameter is java.awt.Graphics2D. This is ImagePanel line 631 from the stack trace below:

painter.paint((Graphics2D) gfx, scaledImage, image, props);

Finally, the stack trace when using the --illegal-access=debug. Potentially interesting bit in bold:

WARNING: Illegal reflective access by org.mozilla.javascript.MemberBox (file:/home/brad/dev/photogrok/rhino-1.7.7.2.jar) to method sun.java2d.SunGraphics2D.drawString(java.lang.String,float,float)
at org.mozilla.javascript.MemberBox.invoke(MemberBox.java:126)
at org.mozilla.javascript.NativeJavaMethod.call(NativeJavaMethod.java:225)
at org.mozilla.javascript.optimizer.OptRuntime.callN(OptRuntime.java:52)
at org.mozilla.javascript.gen.c_4._c_anonymous_1(:7)
at org.mozilla.javascript.gen.c_4.call()
at org.mozilla.javascript.ContextFactory.doTopCall(ContextFactory.java:399)
at org.mozilla.javascript.ScriptRuntime.doTopCall(ScriptRuntime.java:3452)
at org.mozilla.javascript.gen.c_4.call()
at org.mozilla.javascript.InterfaceAdapter.invokeImpl(InterfaceAdapter.java:137)
at org.mozilla.javascript.InterfaceAdapter$1.run(InterfaceAdapter.java:83)
at org.mozilla.javascript.Context.call(Context.java:526)
at org.mozilla.javascript.ContextFactory.call(ContextFactory.java:509)
at org.mozilla.javascript.InterfaceAdapter.invoke(InterfaceAdapter.java:86)
at org.mozilla.javascript.jdk13.VMBridge_jdk13$1.invoke(VMBridge_jdk13.java:132)
at com.sun.proxy.$Proxy6.paint(Unknown Source)
at photogrok.ImagePanel.paintComponent(ImagePanel.java:631)
at java.desktop/javax.swing.JComponent.paint(JComponent.java:1075)
at java.desktop/javax.swing.JComponent.paintChildren(JComponent.java:908)
at java.desktop/javax.swing.JComponent.paint(JComponent.java:1084)
at java.desktop/javax.swing.JComponent.paintChildren(JComponent.java:908)
at java.desktop/javax.swing.JSplitPane.paintChildren(JSplitPane.java:1024)
at java.desktop/javax.swing.JComponent.paint(JComponent.java:1084)
at java.desktop/javax.swing.JComponent.paintChildren(JComponent.java:908)
at java.desktop/javax.swing.JSplitPane.paintChildren(JSplitPane.java:1024)
at java.desktop/javax.swing.JComponent.paint(JComponent.java:1084)
at java.desktop/javax.swing.JComponent.paintChildren(JComponent.java:908)
at java.desktop/javax.swing.JComponent.paint(JComponent.java:1084)
at java.desktop/javax.swing.JComponent.paintChildren(JComponent.java:908)
at java.desktop/javax.swing.JComponent.paint(JComponent.java:1084)
at java.desktop/javax.swing.JComponent.paintChildren(JComponent.java:908)
at java.desktop/javax.swing.JComponent.paint(JComponent.java:1084)
at java.desktop/javax.swing.JLayeredPane.paint(JLayeredPane.java:590)

Johan Compagner

unread,
May 2, 2018, 10:40:04 AM5/2/18
to mozill...@googlegroups.com
problem is that  java.awt.Graphics2D is an abstract class
The real class that you get is very likely the sun.* one

Then the reflection of NativeJavaMethod/Member box really calls method on the actual class not the abstract class..
(drawString method is also abstract, so rhino is really calling a concrete one)

So this is kind of tricky rhino doesn't know you really are talking java.awt.XXx you only give rhino the actual class and then you call drawString...

So somehow there must be a way that you say to that whole MemberBox that the method that it has must be called on a interface/abstract class but then on an actual instance...


Michael Hall

unread,
May 2, 2018, 12:16:26 PM5/2/18
to mozill...@googlegroups.com
On May 2, 2018, at 9:39 AM, Johan Compagner <jcomp...@gmail.com> wrote:

problem is that  java.awt.Graphics2D is an abstract class
The real class that you get is very likely the sun.* one

It looks like you might be right. See the following.

Quick googling didn’t show any solutions.
This
does some discussion on the use of reflection across releases.

The following…

jshell
|  Welcome to JShell -- Version 9
|  For an introduction type: /help intro


jshell> import java.awt.image.*

jshell> BufferedImage img = new BufferedImage(5,5,BufferedImage.TYPE_INT_ARGB)
img ==> BufferedImage@6c3708b3: type = 2 DirectColorModel ... 0 yOff = 0 dataOffset[0] 0

jshell> java.awt.Graphics2D g2d = img.createGraphics()
g2d ==> sun.java2d.SunGraphics2D[font=java.awt.Font[famil ... .Color[r=255,g=255,b=255]]

jshell> g2d.getClass()
$4 ==> class sun.java2d.SunGraphics2D



Gregory Brail

unread,
May 2, 2018, 12:56:25 PM5/2/18
to mozill...@googlegroups.com
I think that's exactly what's happening -- via reflection, MemberBox is invoking an interface method, but the runtime doesn't know that and thinks that it's invoking something that's not exported by the module.

I wonder if it's possible to put some smarts in MemberBox to introspect on the inheritance hierarchy of the method it's supposed to invoke, figure out the top-level interface it came from, and explicitly create a Method object for that rather than the thing that was passed in directly.

I also wonder if the new-ish MethodHandle mechanism (part of invokedynamic support from Java 7) works differently and MemberBox could try using that.


Brad Grier

unread,
Jul 25, 2018, 11:01:58 AM7/25/18
to mozilla-rhino
Nashorn is being deprecated. It's not a huge deal for me as my software can also use Rhino. That said, if a future JDK disallows the types of operations discussed here, even Rhino won't be an option.
Reply all
Reply to author
Forward
0 new messages