Dan Smith - this is a request for a change to one line of the Nestmates JVMS 
5.4.5 Overriding.
The rest of the wording for 5.4.5 is an improvement, so thank you.

Dan Heidinga, Graham Chapman (IBM) and I met to discuss the JVM implementations 
of
JVMS 5.4.5 Overriding, specifically to discuss the expectations relative to the
bullet describing transitive overriding that was added for CFV 51 in JDK7.

The JVMS 9 bullet says:
 mC overrides a method m' (m' distinct from mC and mA) such that m' overrides 
mA.

The proposed NestMates bullet says:
mC overrides a method m' (m' distinct from mC and mA) such that m' overrides mA 
mA is marked neither ACC_PUBLIC nor ACC_PROTECTED nor ACC_PRIVATE, and, where 
mC is declared in a class C and mA is declared in a class A, there exists a 
method mB declared in a class B, such that C is a subclass of B, B is a 
subclass of A, mC can override mB, and mB can override mA.
From examining a number of test cases, we would like to request that the 
updated version be modified to remove the restriction on mA as package private. 
We need to perform what I call transitive overriding checks as long as mA is 
not ACC_PRIVATE.

Dan H also suggested it would be very helpful to all of us if you could add 
some non-normative examples in the spec here. Examples that might be useful 
would be:

1. reason we added transitive overriding to start with - see postscript

2. example of why we need to do the transitive overriding even if mA is 
public/protected as well as package private: (test 841 from our internal test 
matrix for invoke virtual)

>  841|   A PUB        a.B PP     b.C PUB
>  
> call A with B - B.m (B overrides A)
> call A with C - C.m (C overrides A)
> call B with C - B.m (C does not override B)


3. a fix we had to make in 2014:
P1.A: public m()
P2.B extends A, PP m()
P1.C extends B, public m()

P1.C.m() needs to override P1.A.m() and can not override P2.B.m()


thanks,
Karen

p.s. extract from JVMS Clarifications and Addenda to 2nd edition (since the 
original link is gone):

With classfile version 51, which is introduced in JDK7, the invokevirtual 
behavior will be fixed to match the clarifications in the JVMS which were made 
to handle the following test case:

Description of the original problem from: Why the Definition of Method Override 
was Revised:
package P1;

class A {
  void m(){System.out.println("A.m");}
  public void callM(){ m();}
}

public class B extends A {
   protected void m() { System.out.println("B.m");}
}

package P2;

class C extends P1.B {
  protected void m(){ System.out.println("C.m");}

  public static void main(String[] args) {
    C c = new C();
    c.callM();
}
Given the original definition of override, we find that the method m() declared 
in C overrides the method m() declared in B(), since it has the same name and 
signature and is accessible from class C. However, we a lso find that the 
method m() declared in C does not override the method m() declared in A(), 
since it is private to package P1 and therefore not accessible from class C.
In this case, invoking callM() on an instance of C causes a call of m() where 
the target of the method invocation is an instance of C as well. However, this 
call is in the class P1.A, and is attempting to invoke a package private method 
of A. Since this method is not overridden by C, the code will not print "C.m" 
as expected. Instead, it prints "B.m".
This is quite unintuitive, and also incompatible with the behavior of the 
classic VM.
We believe that this interpretation, while literally accurate, is undesirable. 
It prevents a package private method from ever being overridden outside its 
package, even if a subclass within the package has increased the method's 
accessibility.

Therefore invokevirtual was modified in JVMS Clarifications and Addenda to 2nd 
edition to: 

Let C be the class of objectref. The actual method to be invoked is selected by 
the following lookup procedure:

If C contains a declaration for an instance method M with the same name and 
descriptor as the resolved method, and M overrides the resolved method, then M 
is the method to be invoked, and the lookup procedure terminates.

Otherwise, if C has a superclass, this same lookup procedure is performed 
recursively using the direct superclass of C ; the method to be invoked is the 
result of the recursive invocation of this lookup procedure.

Otherwise, an AbstractMethodError is raised.

From the JVMS 2nd edition invokevirtual:

Let C be the class of objectref. The actual method to be invoked is selected by 
the following lookup procedure:

If C contains a declaration for an instance method with the same name and 
descriptor as the resolved method, and the resolved method is accessible from 
C, then this is the method to be invoked, and the lookup procedure terminates.

Otherwise, if C has a superclass, this same lookup procedure is performed 
recursively using the direct superclass of C ; the method to be invoked is the 
result of the recursive invocation of this lookup procedure.

Otherwise, an AbstractMethodError is raised.

Note: the key difference here is the phrase: "the resolved method is accessible 
from C" which in the Clarifications and Addenda has been replaced with "M 
overrides the resolved method"

Reply via email to