Proxy classes and reflection (IllegalAccessException)
David M. Lloyd
david.lloyd at redhat.com
Thu Apr 7 20:22:12 UTC 2016
Having the proxy class be public in most circumstances is a
15-plus-year-old contract. You can't justify breaking it out of the blue
by saying "well it's deprecated now". Deprecating this method is fine,
but you can't break it at the same time. There are two problems here,
and they're both Jigsaw problems.
The first problem is that a magic dynamic module is created for proxy
classes. This is a bit of a punt because of the natural
dissonance/chaos that arises from decoupling the module from the class
loader; however there's possibly a better way to mitigate this: let the
layer decide how to place the proxy class into a *real* module the same
way that in the past, the proxy class was placed into the real class
loader as a normal (usually public) class.
The second problem is that the requirement for adding read edges all
over the place for reflection is unreasonable (and has already been
recognized as such by the EG). I'd argue that this should be completely
generalized: read edges as a whole are not a good solution to the
encapsulation problem; the "friend" package approach which has been
proposed by myself and others has many clear advantages, not the least
of which is to guarantee that "public" means "public" in all
circumstances, and that encapsulation enforcement can be done by the JVM
by the classic team of the bytecode verifier and the linker, which do
this job well today for all non-public relationships. Fixing this
problem not only means that the first problem essentially goes away
(because public is public no matter what module it's in), but also that
more powerful proxy classes could be constructed which have access to
multiple non-public package classes, using the more elegant security
mechanism.
On 04/07/2016 08:29 AM, Remi Forax wrote:
> The problem is that RestEasy is using getProxyClass() which is deprecated in 9.
>
> RestEasy want to do a call to Constructor.newInstance on a constructor of the proxy class,
> and as Stephane said, RestEasy (which is in the unamed module in your case) do not have access to the proxy class which is in a dynamic module
>
> quote from the javadoc of j.l.r.Proxy
> "
> Dynamic Modules
>
> A dynamic module is a named module generated at runtime. A proxy class defined in a dynamic module is encapsulated and not accessible to any module. Calling Constructor.newInstance(Object...) on a proxy class in a dynamic module will throw IllegalAccessException; Proxy.newProxyInstance method should be used instead.
> "
>
> so the solution is easier to add a read edge in the code of RestEasy as Stephane said or to change the code of RestEasy to use newProxyInstance() instead.
>
> regards,
> Rémi
>
> ----- Mail original -----
>> De: "Stephane Epardaud" <stef at epardaud.fr>
>> À: jigsaw-dev at openjdk.java.net
>> Envoyé: Jeudi 7 Avril 2016 15:02:28
>> Objet: Re: Proxy classes and reflection (IllegalAccessException)
>>
>> No, you have to add a read to the module of the class you're proxying,
>> not com.sun.proxy. That'd be your application's module.
>>
>> On 07/04/16 14:25, Neil Bartlett wrote:
>>> Stephane, I don’t think that would help since the package is not exported:
>>> "module jdk.proxy2 does not export com.sun.proxy.jdk.proxy2”.
>>>
>>> Regards,
>>> Neil
>>>
>>>> On 7 Apr 2016, at 13:13, Stephane Epardaud <stef at epardaud.fr> wrote:
>>>>
>>>> IIRC RestEasy needs to add a module read to that Class's module it wants
>>>> to create a Proxy of.
>>>>
>>>> On 07/04/16 14:05, Alan Bateman wrote:
>>>>> On 07/04/2016 12:39, Dawid Weiss wrote:
>>>>>> I don't want to hijack the other thread, so here's a new one I'm stuck
>>>>>> with. I get this exception (simplified stack trace a bit):
>>>>>>
>>>>>> Caused by: java.lang.IllegalAccessException: class
>>>>>> org.jboss.resteasy.core.ContextParameterInjector cannot access class
>>>>>> com.sun.proxy.jdk.proxy2.$Proxy65 (in module jdk.proxy2) because
>>>>>> module jdk.proxy2 does not export com.sun.proxy.jdk.proxy2 to unnamed
>>>>>> module @79ca92b9
>>>>>> at
>>>>>> sun.reflect.Reflection.throwIllegalAccessException(java.base at 9-ea/Reflection.java:411)
>>>>>> at
>>>>>> sun.reflect.Reflection.throwIllegalAccessException(java.base at 9-ea/Reflection.java:402)
>>>>>> at
>>>>>> sun.reflect.Reflection.ensureMemberAccess(java.base at 9-ea/Reflection.java:99)
>>>>>> at
>>>>>> java.lang.reflect.AccessibleObject.slowCheckMemberAccess(java.base at 9-ea/AccessibleObject.java:355)
>>>>>> at
>>>>>> java.lang.reflect.AccessibleObject.checkAccess(java.base at 9-ea/AccessibleObject.java:347)
>>>>>> at
>>>>>> java.lang.reflect.Constructor.newInstance(java.base at 9-ea/Constructor.java:444)
>>>>>> at
>>>>>> org.jboss.resteasy.core.ContextParameterInjector.createProxy(ContextParameterInjector.java:94)
>>>>>> ... 53 more
>>>>>>
>>>>>> I think RestEasy attempts to do create a new instance of a proxy class
>>>>>> here (the complete process here eludes my understanding for now). Any
>>>>>> clues how this can be solved?
>>>>> I assume it should be using newProxyInstance rather that trying to
>>>>> instantiate the proxy class directly. The reason it can't instantiate it
>>>>> directly is because it has been generated into a "dynamic module"
>>>>> (jdk.proxy2 in this case). I assume you'll find that the proxy was
>>>>> created with an interface that is not in an exported package.
>>>>>
>>>>> The "Package and Module Membership of Proxy Class" and "Dynamic Modules"
>>>>> sections of the Proxy javadoc [1] has all the details.
>>>>>
>>>>> -Alan.
>>>>>
>>>>> [1]
>>>>> http://download.java.net/java/jdk9/docs/api/java/lang/reflect/Proxy.html
>>>>>
>>>>>
>>
>>
--
- DML
More information about the jigsaw-dev
mailing list