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