在操作数栈坏类型...使用JDK 8,lambda表达式与匿名内部类失败,为什么?(Bad type

2019-07-03 13:49发布

运行以下错误消息的结果的代码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拉姆达下载 。)

Answer 1:

看来,不仅在发生的情况下,这个问题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 ,那么对异常的意志的原因包括其类型。 例如:

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栈变得破碎。 它可以使用提到的解决方法是固定的。



Answer 2:

编译器错误? 它毕竟是早期版本的访问...

我要说的是,这提到了操作数堆栈的错误信息很可能是由于编译器故障或在JVM中的一个错误。 特别是如果你可以用纯Java的例子得到它。

(它看起来像JVM报道称,本来应该由编译器检测到的类型安全问题,和/或在类加载时字节码校验)。

通过对Java 8臭虫推荐的信道报告。



Answer 3:

不直接关系到你的问题,但我强烈建议不要以这种方式使用匿名类。 你只创建一个全新的HashSet亚型添加两个值它的目的。 这不仅臃肿起来的系统(它停留在记忆永远),也可以混淆JVM的JIT,因为它永远只是看到HashSet的在一个调用位置......它看到你已经创造了许多亚型之一。



文章来源: Bad type on operand stack … using jdk 8, lambdas with anonymous inner classes fails, why?