Access Modifier Issues
Maurizio Cimadamore
maurizio.cimadamore at oracle.com
Fri Jan 9 16:15:04 UTC 2015
On 09/01/15 16:09, Peter Levart wrote:
> On 01/09/2015 04:11 PM, Maurizio Cimadamore wrote:
>>
>> On 09/01/15 14:47, Peter Levart wrote:
>>> On 01/09/2015 03:11 PM, Richard Warburton wrote:
>>>> Hi gents,
>>>>
>>>> Not sure if its a high priority to fix the access modifier problems
>>>> at the
>>>> moment, but there still seems to be a bug with Peter Levart's
>>>> default hack
>>>> which I didn't see reported in the other thread.
>>>
>>> Yes, Maurizio already warned about currently buggy access to private
>>> members from specialized methods. I think you can work-around by
>>> using package-private access for the time being.
>> Exact. The underlying issue is a thorny one: the compiler is
>> organized in 'phases', roughly as follows:
>>
>> source -> parse -> symbol enter -> type-checking -> flow analysis ->
>> erasure -> lambda translation -> misc desugaring -> bytecode
>>
>> With specialization, the pipeline has been modified, so that an extra
>> 'specialize' step is added before erasure takes place (it has to be
>> like that, as we need to save full generic info in the AST).
>> The problem is that inner classes, accessibility and all desugaring
>> is done in a later step (misc desugaring above) - meaning that for
>> all the code generated there, there would be no way to generate the
>> magic specialization attributes. Once you wrap your head around that,
>> it's typically easy to fix the code in order to make it working again
>> (i.e. in this case, tweak access) - of course this problem will be
>> addressed in a more general way.
>>
>> Maurizio
>
> Hm, currently there seem to be two ways of triggering specialization.
> First way is by referencing classes with specialy-crafted names
> (SomeClass${0=?}) and ClassLoader then contains a hook to dispatch to
> the specialization logic. The second is used for invoking specialized
> generic methods, which works with invokedynamic and bootstrap methods.
> Would theoretically be possible to replace the 1st way (special class
> names) with the invokedynamic too? Would it be practical? Would it
> solve access problems?
The current plan is to use a new mechanism called classdynamic for that
purpose (this has come up before in this mailing list). I think,
regardless on which plumbing you use to emit the generated class (either
funky name + Loader changes, or classdyn), if the specialized class is a
brand new class which is completely detached from the class it comes
from, then access (w/o extra accessors) will always be problematic.
Maurizio
>
> Regards, Peter
>
>>>
>>>>
>>>> public class Default<any T> {
>>>>
>>>> private T value;
>>>>
>>>> private Default() {}
>>>>
>>>> public static <any T> T value() {
>>>> return new Default<T>().value;
>>>> }
>>>>
>>>> public static void main(String[] args) {
>>>> int i = Default.value();
>>>> System.out.println(i);
>>>> long l = Default.value();
>>>> System.out.println(l);
>>>> Object o = Default.value();
>>>> System.out.println(o);
>>>> }
>>>>
>>>> }
>>>>
>>>> When running:
>>>>
>>>> Specializing method Default$value${0=I}.value()Ljava/lang/Object; with
>>>> class=[] and method=[I]
>>>> Specializing Default${0=I}; searching for Default.class (not found)
>>>> Specializing Default${0=I}; searching for Default.class (found)
>>>> Exception in thread "main" java.lang.IllegalAccessError: tried to
>>>> access
>>>> method Default${0=I}.<init>()V from class
>>>> Default$value${0=I}/793589513
>>>> at Default$value${0=I}/793589513.value(Default.java:8)
>>>> at Default.main(Default.java:12)
>>>>
>>>> Looks like its workaround-able by making both the constructor and
>>>> value
>>>> field public.
>>>>
>>>> I think this also exposes something I don't understand here. My
>>>> impression
>>>> was that "Default${0=I}" was the specialisation of the class
>>>> Default s.t.
>>>> its first type parameter is an int. So what is "Default$value${0=I}"?
>>>
>>> I think Default$value${0=I}/793589513 is a special (VM-annonymous)
>>> class, containing the specialization of static method
>>> Default.value() for T=int.
>>>
>>> The problem seems to be that private constructor of specialized
>>> class Default for T=int is not accessible from it. The specialized
>>> static method does have access to private members of nonspecialized
>>> class Default (since this is the host class of it's VM-anonymous
>>> class where it is defined), but not to the specialized Default class
>>> for T=int which is a separate class. Perhaps something similar to
>>> how outer class has access to private members of inner classes and
>>> vice-versa would have to be devised among non-specialized classes
>>> and their specializations.
>>>
>>> Regards, Peter
>>>
>>>>
>>>> regards,
>>>>
>>>> Richard Warburton
>>>>
>>>> http://insightfullogic.com
>>>> @RichardWarburto <http://twitter.com/richardwarburto>
>>>
>>
>
More information about the valhalla-dev
mailing list