Re: Nestmates JVMS Overriding 5.4.5 request

2017-11-16 Thread Dan Smith
> On Nov 10, 2017, at 12:48 PM, Karen Kinnear  wrote:
> 
> 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.

The intent is not to change the meaning, but to clarify that the check only 
needs to be performed when mA is package-access. Notice that this appears in a 
list of or'ed conditions, and the first two are "mA is marked ACC_PUBLIC" and 
"mA is marked ACC_PROTECTED". So in those cases, the enclosing "One of the 
following is true" is already true.

If, in fact, some sort of transitive analysis is needed, then the problem is 
deeper than just the access flags checked in this bullet.

Could you supply an example where the current rules define 
unwanted/unimplemented behavior?

> 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:

Sure, some discussion about package access would be helpful. I can do so.

—Dan

Nestmates JVMS Overriding 5.4.5 request

2017-11-10 Thread Karen Kinnear
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 PUBa.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