本文介绍了操作数堆栈上的错误类型...使用jdk 8,带有匿名内部类的lambdas失败,为什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

运行以下代码会导致错误消息操作数堆栈上的错误类型

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);
    }

然而,删除lamda中的双括号初始化(匿名内部类)允许代码按预期运行,为什么?以下工作原理:

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 ...

(除非你有最新的。)

推荐答案

看来,该问题不仅发生在 lambda 返回匿名类型的情况下,但即使在<$内部构造任何匿名类C $ C>拉姆达。即:

It seems, that problem occurs not only in case when lambda returns anonymous type, but even if any anonymous class is constructed inside lambda. I.e.:

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(); }
}

这实际上导致线程中的异常main java.lang.VerifyError:错误的局部变量类型(...)原因:类型top(当前帧,locals [0])不能分配给引用类型

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.

进一步调查显示,如果我们将参数引入方法 xxx ,原因对于异常将包含其类型。例如:

Further investigation shows, that if we will introduce parameter into method xxx, the reason for an exception will contains its type. E.g.:

类型'java / lang / Integer'(当前帧,堆栈[0])不能分配给'lambda / TestLambda'

这已经非常有趣了。让我们将 xxx 参数(实际上并未使用)更改为 top 类的类型,即 TestLambda

And this is already very interesting. Let's change type of xxx parameter (which is not actually used) to type of top class, i.e. TestLambda:

...
    xxx(new TestLambda());
}
private static void xxx(TestLambda x) {
...

你觉得怎么样? 这解决了问题!一切都开始运作良好。甚至,如果我们将更改为A(); 返回,则返回新的A(){}; 。检查一下!

And what do you think? This fixes the problem! Everything begin work well. Even, if we will change return A(); to return new A() {};. Check this!

我的结论是这是真正的 JVM bug 。看来,问题在于加载类的堆栈。它与方法结合使用, Java 用于翻译 lambda 表达式( - 它产生了顶级类中的合成方法。看来,当在 lambda 中引入匿名类时,堆栈就会被破坏。它可以使用上面提到的解决方法来修复。

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 Java uses for translating lambda expressions (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 in lambda stack becomes broken. It could be fixed using mentioned workaround.

这篇关于操作数堆栈上的错误类型...使用jdk 8,带有匿名内部类的lambdas失败,为什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-31 05:34