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.