Consider the following case:
public interface I1 { private static void m() {} }
public class T2 implements I1 { }
Call site: T2 { invokeinterface I1.m()V T2; }
There are 2 inconsistencies here:
- I1.m isn't accessible to T2
- invokeinterface doesn't accept static methods
VM behavior: IncompatibleClassChangeError: Expected instance not static method p1.I2.m()I
JVMS: IllegalAccessError: tried to access method p1.I2.m()I from class p1.T3
My reading of the spec is that the checks during method resolution [1] should precede additional instruction-specific check [2].
[1] 5.4.3.3. Method Resolution.
"Otherwise, if method lookup succeeds but the referenced method is not accessible (��5.4.4) to D, method resolution throws an IllegalAccessError."
[2] 6.5. invokespecial
"Linking Exceptions
During resolution of the symbolic reference to the method, any of the exceptions pertaining to method resolution (��5.4.3.3) can be thrown.
...
Otherwise, if the resolved method is a class (static) method, the invokespecial instruction throws an IncompatibleClassChangeError."
ILW = HLM = P3
I = H = JVMS violation; though error mismatch isn't that serious, it adds noise into the results and hinders results analysis of default method security testing
L = L = forbidden by JLS, but separate compilation may be a source of that
W = M = Incorrect exception can be "translated" if necessary