VerifyError (original) (raw)
Remi Forax forax at univ-mlv.fr
Sat Apr 20 14:48:53 PDT 2013
- Previous message: VerifyError
- Next message: VerifyError
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
On 04/20/2013 08:37 PM, Richard Warburton wrote:
Hi,
Just reporting a verify error (from b86 binary) java.lang.VerifyError: Bad type on operand stack Exception Details: Location: org/adoptajsr/java8/Java8Recommender.lambda$2(Ljava/util/List;)Ljava/util/stream/Stream; @13: invokedynamic Reason: Type 'java/util/List' (current frame, stack[2]) is not assignable to 'org/adoptajsr/java8/Java8Recommender' Current Frame: bci: @13 flags: { } locals: { 'java/util/List' } stack: { 'java/util/stream/Stream', 'java/util/stream/Stream', 'java/util/List' } Bytecode: 0000000: 2ab9 0004 0100 2ab9 0004 0100 2aba 002b 0000010: 0000 b800 2cb0 at org.adoptajsr.java8.Java8RecommenderTest.example(Java8RecommenderTest.java:18) Code is available at: https://github.com/RichardWarburton/java-8-benchmarks/blob/master/java-8-benchmarks/src/main/java/org/adoptajsr/java8/Java8Recommender.java regards, Richard Warburton http://insightfullogic.com @RichardWarburto <http://twitter.com/richardwarburto>
It's a compiler issue, in the following expression, the lambda used as parameter of flatMap is not able to create CoBuy::new correctly
// product id -> product id -> frequency purchased together Map<Integer, Map<Integer, Long>> productSimilarity = buysByUser.values() .stream() .flatMap(buys -> zip(buys.stream(), buys.stream(), CoBuy::new)) .collect(groupingBy(coBuy -> coBuy.x, groupingBy(coBuy -> coBuy.y, TreeMap::new, counting())));
so the bug is here: buys -> zip(buys.stream(), buys.stream(), CoBuy::new)
CoBuy is declared as a non static inner class (BTW, Richard, I think you forget to declare it static) so it capture 'this' which is an instance of Java8Recommender.
javac generates the following code:
private static java.util.stream.Stream lambda$2(java.util.List); Code: 0: aload_0 1: invokeinterface #4, 1 // InterfaceMethod java/util/List.stream:()Ljava/util/stream/Stream; 6: aload_0 7: invokeinterface #4, 1 // InterfaceMethod java/util/List.stream:()Ljava/util/stream/Stream; 12: aload_0 13: invokedynamic #43, 0 // InvokeDynamic #8:lambda$:(LJava8Recommender;)Ljava/util/function/BiFunction; 18: invokestatic #44 // Method java/util/stream/Streams.zip:(Ljava/util/stream/Stream;Ljava/util/stream/Stream;Ljava/util/function/BiFunction;)Ljava/util/stream/Stream; 21: areturn
if you take a look to bytecode 12, instead of pushing 'this' (which is not materialized as a parameter anyway), the compiler push the argument of the lambda ('buys' in the source code). I think it's because both lies in local variable 0 but not in the same stack frame.
here is a simple test case to reproduce the bug: import java.util.function.Supplier; import java.util.function.Consumer;
class Bug2 { class Inner { Inner() { } }
void m() { foo(s -> bar(Inner::new)); }
static void foo(Consumer consumer) { }
static void bar(Supplier supplier) {
}
public static void main(String[] args) { new Bug2().m(); } }
while investigating this issue, I found another related issue, if the lambda take no parameter, the compiler throw an exception.
import java.util.function.Supplier;
class Bug { class Inner { Inner() { } }
void m() { foo(() -> bar(Inner::new)); }
static void foo(Runnable runnable) { }
static void bar(Supplier supplier) {
}
public static void main(String[] args) { new Bug().m(); } }
stack trace: java.lang.NullPointerException at com.sun.tools.javac.jvm.Code.emitop0(Code.java:546) at com.sun.tools.javac.jvm.Items$SelfItem.load(Items.java:367) at com.sun.tools.javac.jvm.Gen.genArgs(Gen.java:913) at com.sun.tools.javac.jvm.Gen.visitApply(Gen.java:1752) at com.sun.tools.javac.tree.JCTree$JCMethodInvocation.accept(JCTree.java:1440) at com.sun.tools.javac.jvm.Gen.genExpr(Gen.java:894) at com.sun.tools.javac.jvm.Gen.genArgs(Gen.java:913) at com.sun.tools.javac.jvm.Gen.visitApply(Gen.java:1752) at com.sun.tools.javac.tree.JCTree$JCMethodInvocation.accept(JCTree.java:1440) at com.sun.tools.javac.jvm.Gen.genExpr(Gen.java:894) at com.sun.tools.javac.jvm.Gen.visitExec(Gen.java:1698) at com.sun.tools.javac.tree.JCTree$JCExpressionStatement.accept(JCTree.java:1271) at com.sun.tools.javac.jvm.Gen.genDef(Gen.java:684) at com.sun.tools.javac.jvm.Gen.genStat(Gen.java:719) at com.sun.tools.javac.jvm.Gen.genStat(Gen.java:705) at com.sun.tools.javac.jvm.Gen.genStats(Gen.java:756) at com.sun.tools.javac.jvm.Gen.visitBlock(Gen.java:1094) at com.sun.tools.javac.tree.JCTree$JCBlock.accept(JCTree.java:884) at com.sun.tools.javac.jvm.Gen.genDef(Gen.java:684) at com.sun.tools.javac.jvm.Gen.genStat(Gen.java:719) at com.sun.tools.javac.jvm.Gen.genMethod(Gen.java:969) at com.sun.tools.javac.jvm.Gen.visitMethodDef(Gen.java:942) at com.sun.tools.javac.tree.JCTree$JCMethodDecl.accept(JCTree.java:771) at com.sun.tools.javac.jvm.Gen.genDef(Gen.java:684) at com.sun.tools.javac.jvm.Gen.genClass(Gen.java:2359) at com.sun.tools.javac.main.JavaCompiler.genCode(JavaCompiler.java:753) at com.sun.tools.javac.main.JavaCompiler.generate(JavaCompiler.java:1547) at com.sun.tools.javac.main.JavaCompiler.generate(JavaCompiler.java:1511) at com.sun.tools.javac.main.JavaCompiler.compile2(JavaCompiler.java:909) at com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:868) at com.sun.tools.javac.main.Main.compile(Main.java:516) at com.sun.tools.javac.main.Main.compile(Main.java:376) at com.sun.tools.javac.main.Main.compile(Main.java:365) at com.sun.tools.javac.main.Main.compile(Main.java:356) at com.sun.tools.javac.Main.compile(Main.java:77) at com.sun.tools.javac.Main.main(Main.java:62)
cheers, Rémi
- Previous message: VerifyError
- Next message: VerifyError
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]