RE: trySetAccessible
Uwe Schindler
uschindler at apache.org
Mon Jul 10 15:31:20 UTC 2017
Hi Alan,
we understand all this. But what you say is also not true. I started a second approach to fix the issue by using canAccess() and also checking the module stuff. For that I executed the following code on the Groovy unnamed module:
import org.codehaus.groovy.reflection.CachedClass;
String.getClass().getModule().isOpen(CachedClass.class.getPackage().getName(), CachedClass.class.getModule());
This returned false, so the java.base module is not open to the package and code hosting Groovy's CachedClass! But setAccessible still works with a warning.
If I do the same using another class from Groovy's own unnamed module, it returns true (as expected). If I call the same with a test of StringBuilder instead of CachedClass it returns true. If I try to access sun.misc.Unsafe that way, it works (as expected, because its declared as "open" in module descriptor - for good reasons, also if you don't permit illegal accesses).
So the module is definitely not "offically open" to the Groovy/unnamed module according to its metadata in java.lang.Module!
Because of this, many people were under the impression that the "open" hack only applied to the "old" setAccessible API, but new Java 9 APIs would behave in the new way. Because of this I understood Mark Reinhold's original proposal mail like this: old-style setAccessible still works with warning, all new APIs (trySetAccessible and Module metadata still say "the computer says no!"). Actually only the module metadata return the correct thing, trySetAccessible behaves like the old setAccessible.
So what we need to fix the issue: Give us an API that we can ask "is access possible" if I respect the module system and the module metadata?
I hacked this in a second attempt to solve Groovy's issue by using the above module metadata. Whenever it figures out that a class returns false for above's call, it does not even try to call setAccessible. See the code here:
https://goo.gl/JnrNyH
This works but the problem is that it is then hard to figure out which methods you can still call without setAccessible. With trySetAccessible or canAccess this would be fine. The problem for Groovy with canAccess() is that you need an instance, which is not available at the time of the check. Why is this? Why do I need an instance for canAccess() checks? I have the feeling because it could be a subclass of the reflected class you try the method call on, right?
Uwe
-----
Uwe Schindler
uschindler at apache.org
ASF Member, Apache Lucene PMC / Committer
Bremen, Germany
http://lucene.apache.org/
> -----Original Message-----
> From: jigsaw-dev [mailto:jigsaw-dev-bounces at openjdk.java.net] On Behalf
> Of Alan Bateman
> Sent: Monday, July 10, 2017 11:56 AM
> To: Cédric Champeau <cedric.champeau at gmail.com>
> Cc: jigsaw-dev <jigsaw-dev at openjdk.java.net>
> Subject: Re: trySetAccessible
>
> On 10/07/2017 09:49, Cédric Champeau wrote:
> > I second Uwe's comment here: I was surprised as well, I expected the
> > semantics of `trySetAccessible` to be: "let me know if I can do this,
> > respecting the semantics of modules, and if not, return false"
> For the example, trySetAccessible succeeds (returns `true`) because
> `java.lang` is open. If you run with `--illegal-access=deny` then
> `java.lang` will not be opened and trySetAccessible should return `false`.
>
> -Alan
More information about the jigsaw-dev
mailing list