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.

Reply via email to