Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 576388

Summary: Wrong bytecode created for varargs invocation when invoking compiler with Java 17 and --release 11
Product: [Eclipse Project] JDT Reporter: Sebastian Ratz <sebastian.ratz>
Component: CoreAssignee: JDT-Core-Inbox <jdt-core-inbox>
Status: CLOSED FIXED QA Contact: Jay Arthanareeswaran <jarthana>
Severity: normal    
Priority: P3 CC: jarthana, loskutov
Version: 4.22   
Target Milestone: ---   
Hardware: All   
OS: All   
Whiteboard:

Description Sebastian Ratz CLA 2021-10-01 06:25:37 EDT
Consider the following class:

Test.java:
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;

public class Test {
	public static int i;

	public static void main(String[] args) throws Throwable {
		MethodHandle methodHandle = MethodHandles.lookup().unreflectGetter(Test.class.getDeclaredField("i"));
		methodHandle.invoke();
	}
}


1) Compile with Java 11; --release 11
$ .../jdk11/bin/java -jar org.eclipse.jdt.core_3.28.0.v20210928-0852.jar Test.java --release 11 -proc:none && java Test
-> OK
$ javap -C Test
15: invokevirtual #37 // Method java/lang/invoke/MethodHandle.invoke:()V


2) Compile with Java 17; --release 17
$ .../jdk17/bin/java -jar org.eclipse.jdt.core_3.28.0.v20210928-0852.jar Test.java --release 17 -proc:none && java Test
-> OK
$ javap -C Test
15: invokevirtual #37 // Method java/lang/invoke/MethodHandle.invoke:()V


3) Compile with Java 17; --release 11
$ .../jdk17/bin/java -jar org.eclipse.jdt.core_3.28.0.v20210928-0852.jar Test.java --release 11 -proc:none && java Test

Exception in thread "main" java.lang.invoke.WrongMethodTypeException: cannot convert MethodHandle()int to (Object[])Object
        at java.base/java.lang.invoke.MethodHandle.asTypeUncached(MethodHandle.java:884)
        at java.base/java.lang.invoke.MethodHandle.asType(MethodHandle.java:869)
        at java.base/java.lang.invoke.Invokers.checkGenericType(Invokers.java:542)

$ javap -C Test
15: iconst_0
16: anewarray     #3  // class java/lang/Object
19: invokevirtual #37 // Method java/lang/invoke/MethodHandle.invoke:([Ljava/lang/Object;)Ljava/lang/Object;
22: pop
Comment 1 Andrey Loskutov CLA 2021-10-02 17:17:54 EDT
I can reproduce on master. Compiling on Java 16 with target 11 works, also on 11/17/16 without target. Only on Java 17 with target 11 fails.

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;

public class Test {
	public static int i;

	public static void main(String[] args) throws Throwable {
		MethodHandle methodHandle = MethodHandles.lookup().unreflectGetter(Test.class.getDeclaredField("i"));
		methodHandle.invoke(); // line 9
		System.out.println("Success");
	}
}

The "working" bytecode for line 9 above looks like

LINENUMBER 9 L1
ALOAD 1: methodHandle
INVOKEVIRTUAL MethodHandle.invoke() : void

The difference with the --release 11 is the following code generated for bad bytecode:

LINENUMBER 9 L1
ALOAD 1: methodHandle
ICONST_0
ANEWARRAY Object
INVOKEVIRTUAL MethodHandle.invoke(Object[]) : Object
POP

Looks like compiler generates an empty array and calls method with this array, as if it would do for "usual" varargs code. MethodHandle.invoke() is however special.

There is a special treatment for MethodHandle.invoke(...) calls, because usually the "wrong" generated code is *expected* for a varargs method call. But I have no idea where in the compiler the MethodHandle.invoke(Object...) is "translated" to MethodHandle.invoke() call.

Probably there is something fishy with CtSym / Java 11 signatures that are read from Java 17 image via CtSym with --release 11? May be the bug is even in JDK 17 itself.

Jay, any idea where do we translate MethodHandle.invoke(Object...) -> MethodHandle.invoke()?
Comment 2 Sebastian Ratz CLA 2021-10-11 11:32:36 EDT
(In reply to Andrey Loskutov from comment #1)
> Probably there is something fishy with CtSym / Java 11 signatures that are
> read from Java 17 image via CtSym with --release 11? May be the bug is even
> in JDK 17 itself.

Compiling with

  .../jdk17/bin/javac --release 11

results in the correct byte-code.
Comment 3 Sebastian Ratz CLA 2022-07-11 07:59:55 EDT
Still seeing this on JDT Core 3.30.100.

It only happens when using JDT to compile. Using the standard javac compiler results in the correct bytecode.
Comment 4 Jay Arthanareeswaran CLA 2022-07-12 02:47:23 EDT
I believe this is same as https://github.com/eclipse-jdt/eclipse.jdt.core/issues/147

Sebastian, please grab our latest build and let us know if it works for you.
Comment 5 Sebastian Ratz CLA 2022-07-12 10:12:27 EDT
(In reply to Jay Arthanareeswaran from comment #4)
> I believe this is same as
> https://github.com/eclipse-jdt/eclipse.jdt.core/issues/147
> 
> Sebastian, please grab our latest build and let us know if it works for you.

Indeed, I was not using the latest build yesterday.

I can confirm that with org.eclipse.jdt.core_3.30.100.v20220709-0825.jar the problems is fixed.

Thank you!