Better tools for adjusting to strong encapsulation

Alan Bateman Alan.Bateman at oracle.com
Wed Mar 22 11:23:15 UTC 2017


On 21/03/2017 20:36, Jochen Theodorou wrote:

>
> that means we will get a lot of users asking us, why our runtime does 
> this, even though it is the "fault" of the code using the runtime and 
> not really ours. Because "type that invoked the reflective operation" 
> is very likely again something caller sensitive, right? Well, that 
> will point to our runtime, not to the real perpetrator. I think there 
> is an annotation that could be used to exclude our methods from 
> getting the caller information, but if memory serves me right this is 
> no public api.
>
> What will be the performance penalty of this?
There isn't an annotation or anything else in this proposal to report a 
caller from further up the stack but there are several debugging options 
to reveal the stack traces when you need it (these debugging options 
have been in JDK 9 for a long time and are very useful).

I assume your interest is Groovy where there are indeed some warnings 
that look like Groovy is to blame. For example, I get the following with 
a trivial script containing`println "Hello world!"` :

$ groovy hello.groovy
NOTE: Picked up the following options via JDK_JAVA_OPTIONS:
   --permit-illegal-access
WARNING: --permit-illegal-access will be removed in the next major release
WARNING: Illegal access by org.codehaus.groovy.reflection.CachedClass 
(file:/groovy-2.4.10/lib/groovy-2.4.10.jar) to method 
java.lang.Object.finalize() (permitted by --permit-illegal-access)
WARNING: Illegal access by org.codehaus.groovy.reflection.CachedClass 
(file:/groovy-2.4.10/lib/groovy-2.4.10.jar) to method 
java.lang.Object.clone() (permitted by --permit-illegal-access)
WARNING: Illegal access by org.codehaus.groovy.reflection.CachedClass 
(file:/groovy-2.4.10/lib/groovy-2.4.10.jar) to method 
java.lang.Object.registerNatives() (permitted by --permit-illegal-access)
WARNING: Illegal access by org.codehaus.groovy.vmplugin.v7.Java7$1 
(file:/groovy-2.4.10/lib/groovy-2.4.10.jar) to constructor 
java.lang.invoke.MethodHandles$Lookup(java.lang.Class,int) (permitted by 
--permit-illegal-access)
Hello world!

The user's script is innocent but maybe you are saying that if Groovy 
spins code and that code calls back into the Groovy runtime to do its 
dirty work then Groovy will be blamed?

On the question of performance then it may have an impact, it might not 
as it depends on how much illegal access is going on. We see some 
libraries doing some hacking with setAccessible(true) at startup and 
then re-using the AccessibleObject over and over, they will hardly 
notice anything.

In the case of Groovy then running with 
JDK_JAVA_OPTIONS="-Dsun.reflect.debugModuleAccessChecks=true" reveals 
several places where  InaccessibleObjectException is being thrown and 
silently ignored, e.g:

java.lang.reflect.InaccessibleObjectException: Unable to make private 
java.lang.invoke.MethodHandles$Lookup(java.lang.Class,int) accessible: 
module java.base does not "opens java.lang.invoke" to unnamed module 
@43bd930a
     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.Constructor.checkCanSetAccessible(Constructor.java:192)
     at 
java.base/java.lang.reflect.Constructor.setAccessible(Constructor.java:185)
     at org.codehaus.groovy.vmplugin.v7.Java7$1.run(Java7.java:53)
     at java.base/java.security.AccessController.doPrivileged(Native Method)
     at org.codehaus.groovy.vmplugin.v7.Java7.<clinit>(Java7.java:50)
     at 
java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native 
Method)
     at 
java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
     at 
java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
     at 
java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:488)
     at java.base/java.lang.Class.newInstance(Class.java:558)
     at 
org.codehaus.groovy.vmplugin.VMPluginFactory.createPlugin(VMPluginFactory.java:59)
     at 
org.codehaus.groovy.vmplugin.VMPluginFactory.<clinit>(VMPluginFactory.java:40)
     at 
org.codehaus.groovy.runtime.metaclass.MetaClassRegistryImpl.<init>(MetaClassRegistryImpl.java:102)
     at 
org.codehaus.groovy.runtime.metaclass.MetaClassRegistryImpl.<init>(MetaClassRegistryImpl.java:74)
     at groovy.lang.GroovySystem.<clinit>(GroovySystem.java:36)
     at 
org.codehaus.groovy.runtime.InvokerHelper.<clinit>(InvokerHelper.java:66)
     at groovy.lang.GroovyObjectSupport.<init>(GroovyObjectSupport.java:34)
     at groovy.lang.Binding.<init>(Binding.java:35)
     at groovy.lang.GroovyShell.<init>(GroovyShell.java:74)
     at groovy.ui.GroovyMain.processOnce(GroovyMain.java:651)
     at groovy.ui.GroovyMain.run(GroovyMain.java:384)
     at groovy.ui.GroovyMain.process(GroovyMain.java:370)
     at groovy.ui.GroovyMain.processArgs(GroovyMain.java:129)
     at groovy.ui.GroovyMain.main(GroovyMain.java:109)
     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:563)
     at 
org.codehaus.groovy.tools.GroovyStarter.rootLoader(GroovyStarter.java:109)
     at org.codehaus.groovy.tools.GroovyStarter.main(GroovyStarter.java:131)
Hello world!

So it might be that the cost of these exceptions is already high and 
that doing illegal access (with --permit-illegal-access) will not be 
noticed while the issues are being fixed.

-Alan



More information about the jigsaw-dev mailing list