Is bytecode invokeinterface correct when resolved method from Object?
Liu, Xin
xxinliu at amazon.com
Wed Dec 1 19:04:18 UTC 2021
hi, Alex,
Thanks for the explanation! Indeed, JVMS and JLS are aligned and they
cover Object's methods in the interface. I also understand why
InvokeInterfaceTest::bar() can't compile in my example.
thanks,
--lx
On 12/1/21 2:17 AM, Liu, Xin wrote:
> Hello,
>
> In Java programming language, I think it's legal to invoke
> java.lang.Object's methods via any interface. All classes must be the
> subclass of j.l.Object. Here is my example. Even though the interface
> 'I' doesn't have the symbol getClass, it will certainly resolve it in
> runtime.
>
>
> public class InvokeInterfaceTest {
> interface I {}
> static class Base {
> public static int bar() {
> return 0;
> }
> }
> static class C extends Base implements I {};
>
> public static boolean foo(I o) {
> return o.getClass() == C.class;
> }
>
> // javac compiler-error
> //public static int bar(I o) {
> // return o.bar();
> //}
>
> public static void main(String args[]) {
> I o = new C();
> foo(o);
> }
> }
>
>
> For InvokeInterfaceTest::foo(I o), I didn't make it up. I have seen the
> code like this in ArrayList.
> https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/java/util/ArrayList.java#L183
>
> Until jdk17, javac generates 'invokevirtual' in InvokeInterfaceTest::foo.
>
> public static boolean foo(InvokeInterfaceTest$I);
> Code:
> 0: aload_0
> 1: invokevirtual #7 // Method
> java/lang/Object.getClass:()Ljava/lang/Class;
> 4: ldc #11 // class InvokeInterfaceTest$C
> 6: if_acmpne 13
> 9: iconst_1
> 10: goto 14
> 13: iconst_0
> 14: ireturn
>
>
> The tip of JDK now replaces 'invokevirtual' with invokeinterface, as
> follows.
>
> public static boolean foo(InvokeInterfaceTest$I);
> Code:
> 0: aload_0
> 1: invokeinterface #7, 1 // InterfaceMethod
> InvokeInterfaceTest$I.getClass:()Ljava/lang/Class;
> 6: ldc #13 // class InvokeInterfaceTest$C
> ...
>
>
> Not only each call takes 2 more bytes, I feel it doesn't comply with JVM
> spec. JVMS says that 'invokeinterface' resolves an 'interface method'.
> j.l.Object.getClass() is not an interface method, is it?
> https://docs.oracle.com/javase/specs/jvms/se17/html/jvms-6.html#jvms-6.5.invokeinterface
>
> Is it an intentional change of javac? My concern is that this ambiguity
> makes HotSpot more complex. Further, if it does violate JVMS, it will
> make javac implementation-dependent.
>
> thanks,
> --lx
>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: OpenPGP_0xB9D934C61E047B0D.asc
Type: application/pgp-keys
Size: 3674 bytes
Desc: OpenPGP public key
URL: <https://mail.openjdk.java.net/pipermail/compiler-dev/attachments/20211201/b65dc25e/OpenPGP_0xB9D934C61E047B0D-0001.asc>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: OpenPGP_signature
Type: application/pgp-signature
Size: 665 bytes
Desc: OpenPGP digital signature
URL: <https://mail.openjdk.java.net/pipermail/compiler-dev/attachments/20211201/b65dc25e/OpenPGP_signature-0001.bin>
More information about the compiler-dev
mailing list