Problem with lambda expression in initialization block
Remi Forax
forax at univ-mlv.fr
Sun Sep 16 01:06:14 PDT 2012
On 09/16/2012 02:51 AM, François Sarradin wrote:
> Hi,
>
> I am unable to run a test with a lambda expression in a initialization block.
>
> Here is a code that fails:
>
> /* ---- */
> package testjava8;
>
> import org.junit.Test;
>
> import java.util.HashMap;
> import java.util.Map;
>
> import static org.junit.Assert.assertEquals;
>
>
> public class MyTest {
>
> private static final Map<String, String> M1 = new HashMap<String,
> String>() {{
> put("a", "z");
> put("b", "y");
> }};
>
> private static final Map<String, String> M2 = new HashMap<String,
> String>() {{
> M1.forEach((l1, l2) -> {
> put(l2, l1);
> });
> }};
>
> @Test
> public void should_reverse() {
> assertEquals("a", M2.get("z"));
> }
>
> }
> /* ---- */
>
> Here is the stack trace I get:
>
> 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 testjava8.MyTest$2.<init>(MyTest.java:1)
> at testjava8.MyTest.<clinit>(MyTest.java:18)
> at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
> at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
> at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
> at java.lang.reflect.Constructor.newInstance(Constructor.java:395)
> at org.junit.runners.BlockJUnit4ClassRunner.createTest(BlockJUnit4ClassRunner.java:187)
> at org.junit.runners.BlockJUnit4ClassRunner$1.runReflectiveCall(BlockJUnit4ClassRunner.java:236)
> at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
> at org.junit.runners.BlockJUnit4ClassRunner.methodBlock(BlockJUnit4ClassRunner.java:233)
> at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68)
> at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47)
> at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
> at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
> at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
> at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
> at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
> at org.junit.runners.ParentRunner.run(ParentRunner.java:300)
> at org.junit.runner.JUnitCore.run(JUnitCore.java:157)
> at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:76)
> at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:195)
> at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:63)
> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
> at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
> at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
> Caused by: java.lang.invoke.LambdaConversionException: Unsupported
> MethodHandle kind: MethodHandleInfo[invokeSpecial
> testjava8.MyTest$2.lambda$0(String,String)void]
> at java.lang.invoke.AbstractValidatingLambdaMetafactory.validateMetafactoryArgs(AbstractValidatingLambdaMetafactory.java:172)
> at java.lang.invoke.LambdaMetafactory.metaFactory(LambdaMetafactory.java:165)
> at java.lang.invoke.CallSite.makeSite(CallSite.java:283)
> ... 28 more
>
>
> Regards,
>
> François
>
I suppose that javac translate the lambda as a non static method,
because the inner-class that inherits from HashMap is final,
the VM consider that the method can be called using the super syntax to
avoid
to do a virtual call (I think it's an optimization of the new method
handle backend
that was not previously done) and the lambda conversion code that checks
the type of method handle is too strict and rejects the lambda.
So AbstractValidatingLambdaMetafactory.validateMetafactoryArgs should be
changed to allow
lambda that are constructed with a super call.
cheeers,
Rémi
More information about the lambda-dev
mailing list