adoptium / adoptium-support

For end-user problems reported with our binary distributions
Apache License 2.0
43 stars 15 forks source link

javac (LTS-Versions 11-21) produces incorrect binar-code when using cascading lamdas #1081

Open r-pf opened 4 weeks ago

r-pf commented 4 weeks ago

Please provide a brief summary of the bug

When compiling the source code LamdaWithVarArgsCompilerProblem.java below with javac of one of the versions 21.0.3+9, 17.0.11+9 or 11.0.23+9 (or may be any version of these LTS-Major-Versions 11 - 21) the produced clas-file brings a ClassCastException when executing via java. When compiled with Java 8 e.g. 1.8.0_412-b08 it works well.

Did you test with the latest update version?

Please provide steps to reproduce where possible

Compile the source code below with javac of one of the JDK-Versions 21.0.3+9, 17.0.11+9 or 11.0.23+9 (or may be any version of these LTS-Major-Versions 11 - 21) :

javac LamdaWithVarArgsCompilerProblem.java

Then execute the compiled class-file via java.

LamdaWithVarArgsCompilerProblem.java :

import java.util.function.Consumer;
import java.util.function.Function;

public class LamdaWithVarArgsCompilerProblem {

  @SafeVarargs
  public final <P, T extends Throwable> void exec(
    final Consumer<P[]>  fi,
    final P ...         params
  )throws T
  {
    fi.accept(params);
  }

  @SafeVarargs
  public final <P, R, T extends Throwable> R execute(
    Function<P [], R>  fi1O,
    P ...             params
  )throws T
  {
    R result;

    result = fi1O.apply(params);
    System.out.println(params.getClass() + " - " + result);

    return result;
  }

  public static void main(
    String [] args
  )
  {
    LamdaWithVarArgsCompilerProblem lamdaWithVarArgsCompilerProblem;
    Function<Integer [], Integer>   function;

    lamdaWithVarArgsCompilerProblem = new LamdaWithVarArgsCompilerProblem();

    function = (a) -> Integer.valueOf(1);

          // This will work - `execute` isn't part of a lambda-expression
    lamdaWithVarArgsCompilerProblem.execute(function);

          // This will work - passed Integer-array to lamdaWithVarArgsCompilerProblem.execute(..)
    lamdaWithVarArgsCompilerProblem.exec( 
                      (a) -> lamdaWithVarArgsCompilerProblem.execute(function, new Integer [0]));

          // This will fail at runtime when compiled with Java11, Java17 or Java21
          // An Object [] will be passed to execute(..) instead of an expected Integer []
    lamdaWithVarArgsCompilerProblem.exec( 
                      (a) -> lamdaWithVarArgsCompilerProblem.execute(function));

  }
}

Expected Results

Compiled with 1.8.0_412-b08 => o.k.

user> java -cp . LamdaWithVarArgsCompilerProblem
class [Ljava.lang.Integer; - 1
class [Ljava.lang.Integer; - 1
class [Ljava.lang.Integer; - 1
user> 

Actual Results

Compiled with 21.0.3+9, 17.0.11+9 or 11.0.23+9 => not o.k.

user> java -cp . LamdaWithVarArgsCompilerProblem
class [Ljava.lang.Integer; - 1
class [Ljava.lang.Integer; - 1
Exception in thread "main" java.lang.ClassCastException: class [Ljava.lang.Object; cannot be cast to class [Ljava.lang.Integer; ([Ljava.lang.Object; and [Ljava.lang.Integer; are in module java.base of loader 'bootstrap')
    at LamdaWithVarArgsCompilerProblem.execute(LamdaWithVarArgsCompilerProblem.java:24)
    at LamdaWithVarArgsCompilerProblem.lambda$main$2(LamdaWithVarArgsCompilerProblem.java:51)
    at LamdaWithVarArgsCompilerProblem.exec(LamdaWithVarArgsCompilerProblem.java:12)
    at LamdaWithVarArgsCompilerProblem.main(LamdaWithVarArgsCompilerProblem.java:50)
user> 

An unexpected Object-array is passed. An Integer-array is expected.

What Java Version are you using?

21.0.3+9-LTS, 17.0.11+9 and 11.0.23+9

What is your operating system and platform?

ArchLinux, Windows 10

How did you install Java?

tar xvzf '../OpenJDK21U-jdk_x64_linux_hotspot_21.0.3_9.tar.gz'

tar xvzf '../OpenJDK17U-jdk_x64_linux_hotspot_17.0.11_9.tar.gz'

tar xvzf '../OpenJDK11U-jdk_x64_linux_hotspot_11.0.23_9.tar.gz'

Did it work before?

Yes.

Compiled with 1.8.0_412-b08 => o.k. (see "Expected Results" above)

There is a workaround:
The last (real) code-line is

(a) -> lamdaWithVarArgsCompilerProblem.execute(function));

Replacing this line with

(a) -> {lamdaWithVarArgsCompilerProblem.execute(function);});

is a workaround for this problem.


### Did you test with other Java versions?

```Shell
Compiled with 1.8.0_412-b08 => o.k. (see "Expected Results" above)
Compiled with 21.0.3+9, 17.0.11+9 or 11.0.23+9  => not o.k. (see "Actual Results" above)

Relevant log output

See "Expected Results" and "Actual Results" above.