Class verifier issues with unboxing method handles

David Holmes david.holmes at oracle.com
Tue May 28 18:48:14 PDT 2013


Hi Mark,

cc'ing lambda-dev. This may be a bug, a version mismatch, or something 
else. The lambda-dev folk will know.

David

On 29/05/2013 11:04 AM, Mark Derricutt wrote:
> Hi all,
>
> Mark Reinhold suggested I posted this question/bug report to hotspot-dev
> rather than jdk8-dev so here goes.
>
> I have a fairly simple test case using the new streams API:
>
> public static void main(String[] args) {
> List<String> strings = Arrays.asList("1", "2", "3", "4", "5");
>    strings.stream()
> .mapToInt(s -> new Integer(s))
> .forEach(i -> System.out.println(String.format("int %d", i)));
> }
>
>
> which compiles, runs, and prints out what I expect:
>
> int 1
> int 2
> int 3
> int 4
> int 5
>
>
> Given that mapToInt() is returning an IntegerStream wrapping primitive
> ints, the result of my closure is successfully autoboxed down to an int
> and all is happy with the world.
>
> If I change this code to be:
>
>    strings.stream()
>           .mapToInt(Integer::parseInt)
>           .forEach(i -> System.out.println(String.format("int %d", i)));
>
> Again, everything works as expected as Integer::parseInt returns an int,
> so there's no boxing.
>
> Changing this once again to:
>
>    strings.stream()
>           .mapToInt(Integer::valueOf)
>           .forEach(i -> System.out.println(String.format("int %d", i)));
>
> I also see the expected result, Integer::valueOf returns an Integer
> which is then being boxed down to an int.
>
> However, if I change the code to:
>
>   strings.stream()
>          .mapToInt(Integer::new)
>          .forEach(i -> System.out.println(String.format("int %d", i)));
>
> which, if I understand correctly - Integer::new should be returning a
> method handle to the constructor. IntelliJ IDEA 13 autocompletes this
> for me, and hyperlinks to the Integer(String s) constructor, javac
> successfully compiles the code so my -assumption- is that the
> constructor would be called, returning an Integer which is then boxed
> down to an int, however, this is what I get:
>
> Exception in thread "main" java.lang.BootstrapMethodError: call site
> initialization exception
>      at java.lang.invoke.CallSite.makeSite(CallSite.java:298)
>      at
> java.lang.invoke.MethodHandleNatives.linkCallSite(MethodHandleNatives.java:294)
>
>      at com.talios.test.TestJdk.main(TestJdk.java:12)
>      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>      at
> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
>
>      at
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
>
>      at java.lang.reflect.Method.invoke(Method.java:491)
>      at
> com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
> Caused by: java.lang.VerifyError: Bad type on operand stack
> Exception Details:
>    Location:
>      com/talios/test/TestJdk$$Lambda$1.applyAsInt(Ljava/lang/Object;)I
> @11: ireturn
>    Reason:
>      Type 'java/lang/Integer' (current frame, stack[0]) is not
> assignable to integer
>    Current Frame:
>      bci: @11
>      flags: { }
>      locals: { 'com/talios/test/TestJdk$$Lambda$1', 'java/lang/Object' }
>      stack: { 'java/lang/Integer' }
>    Bytecode:
>      0000000: bb00 0e59 2bc0 0010 b700 13ac
>
>      at java.lang.Class.getDeclaredConstructors0(Native Method)
>      at java.lang.Class.privateGetDeclaredConstructors(Class.java:2536)
>      at java.lang.Class.getDeclaredConstructors(Class.java:1928)
>      at
> java.lang.invoke.InnerClassLambdaMetafactory$1.run(InnerClassLambdaMetafactory.java:147)
>
>      at
> java.lang.invoke.InnerClassLambdaMetafactory$1.run(InnerClassLambdaMetafactory.java:144)
>
>      at java.security.AccessController.doPrivileged(Native Method)
>      at
> java.lang.invoke.InnerClassLambdaMetafactory.buildCallSite(InnerClassLambdaMetafactory.java:143)
>
>      at
> java.lang.invoke.LambdaMetafactory.metaFactory(LambdaMetafactory.java:191)
>      at java.lang.invoke.CallSite.makeSite(CallSite.java:283)
>      ... 7 more
>
> This is on OSX Mountain Lion, with JDK 8 Build 91.
>
> Have I walked in an obscure corner case of method handle breakage and
> found something new, or is this a new problem?
>
> Cheers,
> Mark
>


More information about the lambda-dev mailing list