JDK-8056051 : int[]::clone causes "java.lang.NoClassDefFoundError: Array"
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 8u40
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • OS: linux_ubuntu
  • CPU: x86_64
  • Submitted: 2014-08-21
  • Updated: 2015-06-04
  • Resolved: 2014-10-14
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 8 JDK 9
8u40 b12Fixed 9Fixed
Description
FULL PRODUCT VERSION :
java version "1.8.0_20"
Java(TM) SE Runtime Environment (build 1.8.0_20-b26)
Java HotSpot(TM) 64-Bit Server VM (build 25.20-b23, mixed mode)

A DESCRIPTION OF THE PROBLEM :
JLS ����15.13 says that `int[]::clone` is a valid method reference expression. However, using it causes a "java.lang.NoClassDefFoundError: Array" error.

THE PROBLEM WAS REPRODUCIBLE WITH -Xint FLAG: Yes

THE PROBLEM WAS REPRODUCIBLE WITH -server FLAG: Yes

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compile and run the code listed in "Source code for an executable test case".

EXPECTED VERSUS ACTUAL BEHAVIOR :
I expect the `int[]::clone` and `String[]::clone` to behave the same as `a -> a.clone()`. Instead, they throw a `NoClassDefFoundError`.
ERROR MESSAGES/STACK TRACES THAT OCCUR :
java.lang.NoClassDefFoundError: Array
	at ArrayCloneTest.lambda$MR$main$clone$8ed4b78b$1(ArrayCloneTest.java:8)
	at ArrayCloneTest$$Lambda$3/1555009629.apply(Unknown Source)
	at ArrayCloneTest.lambda$printInt$3(ArrayCloneTest.java:31)
	at ArrayCloneTest$$Lambda$4/149928006.get(Unknown Source)
	at ArrayCloneTest.lambda$printInt$2(ArrayCloneTest.java:27)
	at ArrayCloneTest$$Lambda$5/168423058.get(Unknown Source)
	at ArrayCloneTest.print(ArrayCloneTest.java:19)
	at ArrayCloneTest.printInt(ArrayCloneTest.java:27)
	at ArrayCloneTest.printInt(ArrayCloneTest.java:31)
	at ArrayCloneTest.main(ArrayCloneTest.java:8)
Caused by: java.lang.ClassNotFoundException: Array
	at java.net.URLClassLoader$1.run(URLClassLoader.java:372)
	at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.net.URLClassLoader.findClass(URLClassLoader.java:360)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
	... 10 more

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.util.Arrays;
import java.util.function.Function;
import java.util.function.Supplier;

public class ArrayCloneTest {
    public static void main(String[] args) {
        int[] intArgs = Arrays.stream(args).mapToInt(Integer::parseInt).toArray();
        printInt("int[]::clone", int[]::clone, intArgs);
        printInt("a -> a.clone()", a -> a.clone(), intArgs);
        printInt("intArgs::clone", intArgs::clone);

        printString("String[]::clone", String[]::clone, args);
        printString("a -> a.clone()", a -> a.clone(), args);
        printString("args::clone", args::clone);
    }

    private static void print(String label, Supplier<?> s) {
        try {
            System.out.printf("%s => %s%n", label, s.get());
        } catch (Throwable t) {
            System.err.printf("%s =!> %s%n", label, t);
            t.printStackTrace();
        }
    }

    private static void printInt(String label, Supplier<int[]> s) {
        print(label, () -> Arrays.toString(s.get()));
    }

    private static void printInt(String label, Function<int[], int[]> f, int[] a) {
        printInt(label, () -> f.apply(a));
    }

    private static void printString(String label, Supplier<String[]> s) {
        print(label, () -> Arrays.toString(s.get()));
    }

    private static void printString(String label, Function<String[], String[]> f, String[] a) {
        printString(label, () -> f.apply(a));
    }
}
---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Instead of using `int[]::clone`, use `a -> a.clone()` instead.


Comments
In review
17-09-2014

The array clone method is enclosed a special fake class in the compiler called "Array" -- this fake class would need special handling to fix this bug.
12-09-2014

Looks like a bug in the conversion of a method reference to a lambda
11-09-2014

Minimal test case: import java.util.function.Function; class ArrayCloneTest { public static void main(String[] args) { Function<int[], int[]> f = int[]::clone; f.apply(new int[] {1,2,3}); } } Javap output: private static java.lang.Object lambda$MR$main$clone$8ed4b78b$1(java.lang.Object); descriptor: (Ljava/lang/Object;)Ljava/lang/Object; flags: ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC Code: stack=1, locals=1, args_size=1 0: aload_0 1: checkcast #4 // class Array 4: invokevirtual #5 // Method Array.clone:()Ljava/lang/Object; 7: areturn } The bytecode output is plain wrong as it mentions the 'Array' class - probably a leftover of some compilation type.
01-09-2014