stricter symbolic references to protected methods

Dan Smith daniel.smith at oracle.com
Fri Dec 8 18:30:46 UTC 2017


> On Dec 1, 2017, at 7:48 PM, John Rose <john.r.rose at oracle.com> wrote:
> 
> This is the language I'm talking about:
> 
>> • R is protected and is declared in a class C, and D is either a subclass of C or C itself. Furthermore, if R is not static, then the symbolic reference to R must contain a symbolic reference to a class T, such that T is either a subclass of D, a superclass of D, or D itself.
>> 
>> During verification, it was also required that, even if T is a superclass of D, the target reference of a protected instance field access or method invocation must be an instance of D or a subclass of D (4.10.1.8).
> 
> 
> We could replace it by this:
> 
>> • R is protected and is declared in a class C *not in the same run-time package as D*, and D is *a subclass of C*.

This is fine—just defers the "or C itself" part to the next bullet ("C itself" implies same package).

>> Furthermore the symbolic reference to R must contain a symbolic reference to *the immediate superclass of D*.

So, here's a class hierarchy:

package p1; public class A {
  protected static void m() {}
  protected void n() {}
}

package p2; public class B extends A {
}

package p2; public class C extends B {
}

package p2; public class D extends C {
}

From the body of C, it's legal in Java to say:
A.m(); // invokestatic A.m()V
B.m(); // invokestatic B.m()V
C.m(); // invokestatic C.m()V
C.m(); // invokestatic D.m()V

So your proposed change is bad for static members.

For *instance* members, from the body of C:
void test(A a, B b, C c, D d) {
    a.n(); // error
    b.n(); // error
    c.n(); // ok: invokevirtual C.n()V
    d.n(); // ok: invokevirtual D.n()V
    super.n(); // ok: invokespecial B.n()V
}

The one thing that I think we can safely assert will never be referenced by Java is 'A.n'. One exception, though: for some reason, methods of Object ('clone') are referenced directly via Object, even when, say, the receiver has type C.

So we need to keep the "subclass of D" and "D itself" parts of the rule about T.

From javac's perspective, we could restrict the "superclass of D" part of the rule to mean "direct superclass", as long as we do something about the Object case. At the same time, we would probably want to limit invokespecial to a direct superclass.

>> During verification, it was also required that the target reference of a protected instance field access or method invocation must be an instance of D or a subclass of D (4.10.1.8).

FYI, I believe the only time Java will have a mismatch between the target reference type and the referenced class type is when 'super' is used. Elsewhere, T=<target reference type> and this verification rule isn't needed. (Except for the 'Object' special case, noted above.)

—Dan


More information about the valhalla-spec-observers mailing list