Running the code below results in the error message Bad type on operand stack.
public static void main(String args[]) {
TransformService transformService = (inputs) -> {
return new ArrayList<String>(3) {{
add("one");
add("two");
add("three");
}};
};
Collection<Integer> inputs = new HashSet<Integer>(2) {{
add(5);
add(7);
}};
Collection<String> results = transformService.transform(inputs);
System.out.println(results.size());
}
public interface TransformService {
Collection<String> transform(Collection<Integer> inputs);
}
However removing the double brace initialization (anonymous inner classes) within the lamda allows the code to run as expected, why ? The below works :
public class SecondLambda {
public static void main(String args[]) {
TransformService transformService = (inputs) -> {
Collection<String> results = new ArrayList<String>(3);
results.add("one");
results.add("two");
results.add("three");
return results;
};
Collection<Integer> inputs = new HashSet<Integer>(2) {{
add(5);
add(7);
}};
Collection<String> results = transformService.transform(inputs);
System.out.println(results.size());
}
public interface TransformService {
Collection<String> transform(Collection<Integer> inputs);
}
}
Compiler bug ? It is the early access version after all …
(This won’t compile unless you have the latest jdk 8 lambda download.)
It seems, that problem occurs not only in case when
lambdareturnsanonymoustype, but even if any anonymous class is constructed insidelambda. I.e.:This actually leads to
Exception in thread "main" java.lang.VerifyError: Bad local variable type(…)Reason: Type top (current frame, locals[0]) is not assignable to reference type.Further investigation shows, that if we will introduce parameter into method
xxx, the reason for an exception will contains its type. E.g.:Type 'java/lang/Integer' (current frame, stack[0]) is not assignable to 'lambda/TestLambda'And this is already very interesting. Let’s change type of
xxxparameter (which is not actually used) to type of top class, i.e.TestLambda:And what do you think? This fixes the problem! Everything begin work well. Even, if we will change
return A();toreturn new A() {};. Check this!My conclusion is that this is real JVM bug. It seems, that the problem is with stack of loaded classes. It occurs in combine with method, which
Javauses for translatinglambdaexpressions (http://cr.openjdk.java.net/~briangoetz/lambda/lambda-translation.html) – it produces synthetic methods inside top class. It seems, that when anonymous classes are introduced inlambdastack becomes broken. It could be fixed using mentioned workaround.