Java Virtual Machine Specification (JVMS): Error in "5.4.5 Method Overrides"

I filed the following error on September 28, 2009. Unfortunately, I still have not received any response, and the final version of the specification is still incorrect. Is this really a mistake? If not, why not? If so, what should I do?

Section containing the error, 5.4.5 (method override): http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-5.html#jvms-5.4.5 in conjunction with the INVOKEVIRTUAL opcode description : http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-6.html#jvms-6.5.invokevirtual

According to 5.4.5, m1 can override m2 , even if m1 is closed. This can happen when manually creating .class files or when combining .class from two compilations.

In my example, I have classes A and B with B extends A I compiled these classes, so A contains a public method named f and B contains a private method, also called f (by first declaring both methods public , compiling, copying A.class > to a safe place, deleting the declaration of f in A and changing to private to B , then compile B and using the saved version of A.class ).

When this is done, my current JVM output is Oracle A (which means the method f in A ). According to the specification, B must be the result (which means that the method f in B must be called).

EDIT: Actually, Bf should be allowed. The call may fail due to access authorization for the permitted method if the caller is not B However, I believe that part of the method resolution is incorrect.

I think the definition in 5.4.5 should check the permissions of m1 , not just m2 .

 public class A { public void f(); Code: 0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream; 3: ldc #3 // String A 5: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 8: return } public class B extends A { private void f(); Code: 0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream; 3: ldc #3 // String B 5: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 8: return } 

Thanks Karsten

+4
source share
1 answer

Finally, the problem has been resolved. The current version of the Java 8 JVM specification contains the necessary explanations:

5.4.5 Override

The instance method m C declared in class C overrides another instance method m A declared in class A if either m C matches m A or all of the following is true:

  • C is a subclass of A.
  • m C has the same name and descriptor as m A.
  • m C not marked ACC_PRIVATE.
  • One of the following statements is true:
    • m A is marked ACC_PUBLIC; or marked ACC_PROTECTED; or neither ACC_PUBLIC, ACC_PROTECTED or ACC_PRIVATE is marked, and A belongs to the same run-time package as C.
    • m C redefines the method m '(m' other than m C and m A ), so m 'redefines m Asub>.

In section 4.10.1.5 there is another addition: "Type checking of abstract and native methods":

private methods and static methods are orthogonal for sending dynamic methods, so they never override other methods (Β§5.4.5).

Less than five years to fix, this is quick compared to some other problems ...

+1
source

All Articles