VerifyError

Remi Forax forax at univ-mlv.fr
Sat Apr 20 14:48:53 PDT 2013


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<String> consumer) {
   }

   static void bar(Supplier<Inner> 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<Inner> 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



More information about the lambda-dev mailing list