Updated VM-bridges document

Brian Goetz brian.goetz at oracle.com
Thu Apr 11 23:04:15 UTC 2019



On 4/11/2019 5:18 PM, Karen Kinnear wrote:
>>
>> OK, so at this point, the classfiles that have been loaded look like:
>>
>>     class D {
>>         void m(LDT) { real method }
>>         @Forwarding(m(LDT)) abstract void m(Date);
>>     }
>>
>>     class E extends D {
>>         @Override
>>         m(Date) { impl }
>>     }
>>
>> So D has members m(LTD) and m(Date), the latter is a forwarder.  
>> Therefore E has the same members (instance methods are inherited).
> From a source perspective, E has the same names of members, although 
> it has overridden the contents of m(Date).
>
>>
>> Here's how I would imagine this turns into in the VM:
> not important, but this was m(LDT) not m(LTD)
>>
>>     class D {
>>         void m(LTD) { real method }
>>         void m(Date d) { m(adapt(d)); }  // generated forwarder
>>     }
>>
>>     class E extends D {
>>         private void m$synthetic(Date d) { real method, body as 
>> present in classfile }
> I would expect that the existing m(Date) with the real method would 
> stay unchanged - including
> the name and the access controls - since there may be clients of 
> subclass E still trying to invoke it.

I think this is our point of disconnect.

The subclass has overridden a forwarder.  What we want to do is "heal 
the rift" by rewriting the subclass as if it had _only_ overridden the 
real method.  Hence, the "shunt it off to a synthetic" and create an 
overriding reverser that overrides the real method, adapting 
args/return, which delegates to the shuntee.

If we left m(Date) in E, then this would be overriding the forwarder, 
effectively un-doing the effect of forwarding.

Note that this is all "as if"; there are a hundred ways to _actually_ do 
it.


More information about the valhalla-spec-observers mailing list