运行以下代码会导致错误消息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);
}
然而,删除lamda中的双括号初始化(匿名内部类)允许代码按预期运行,为什么?以下作品:
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);
}
}
编译器错误?毕竟这是早期的访问版本......
(除非你有最新的jdk 8 lambda download,否则不会编译。)
答案 0 :(得分:7)
看起来,问题不仅发生在lambda
返回anonymous
类型的情况下,而且即使在lambda
内构造了任何匿名类。即:
public class TestLambda {
public static void main(String[] args) {
xxx();
}
static void xxx() {
Functional1 f = () -> {
Object o = new Object() { };
return new A();
};
}
static class A { }
static interface Functional1 { A func(); }
}
这实际上会导致Exception in thread "main" java.lang.VerifyError: Bad local variable type
(...)Reason: Type top (current frame, locals[0]) is not assignable to reference type
。
进一步调查显示,如果我们将参数引入方法xxx
,则异常的原因将包含其类型。 E.g:
Type 'java/lang/Integer' (current frame, stack[0]) is not assignable to 'lambda/TestLambda'
这已经非常有趣了。我们将xxx
参数(实际上未使用)的类型更改为顶部类的类型,即TestLambda
:
...
xxx(new TestLambda());
}
private static void xxx(TestLambda x) {
...
你觉得怎么样? 这解决了问题!一切都开始运作良好。即使我们将return A();
更改为return new A() {};
也是如此。检查一下!
我的结论是,这是真正的 JVM错误。似乎问题是加载类的堆栈。它与方法结合使用,Java
用于翻译lambda
表达式(http://cr.openjdk.java.net/~briangoetz/lambda/lambda-translation.html) - 它在顶级类中生成合成方法。看来,当lambda
堆栈中引入匿名类时,它就会被破坏。它可以使用上面提到的解决方法来修复。
答案 1 :(得分:2)
编译器错误?毕竟这是早期的访问版本......
我想说任何提到操作数堆栈的错误消息很可能是由于编译器错误或JVM中的错误。特别是如果你可以使用纯Java示例来获取它。
(看起来JVM正在报告编译器应该检测到的类型安全问题,和/或类加载时的字节码验证程序。)
通过推荐的Java 8错误频道报告。
答案 2 :(得分:1)
与您的问题没有直接关系,但我强烈建议不要以这种方式使用匿名类。您只是为了向其添加两个值而创建一个全新的HashSet子类型。这不仅会使系统膨胀(它永远留在内存中),它也会混淆JVM的JIT,因为它永远不会在呼叫站点看到HashSet ......它会看到你创建的许多子类型之一。