Java 8 nested lambdas break compiler
Asked Answered
G

1

10

i have a complex problem with Java 8.

Problem

With nested lambda compiler crash with a NullPointerException!

I know that lambdas must be stateless indeed in this case the codes that have state are Supplier implementations that however are anonymous classes and not lambdas.

Code

import java.util.function.Function;
import java.util.function.Supplier;

public class Test {

    public static Function<String, Supplier<String>> A = aVal -> new Supplier<String>() {

        @Override
        public String get() {
            return B.apply(aVal).get();
        }

        private Function<String, Supplier<String>> B = bVal -> new Supplier<String>() {
            @Override
            public String get() {
                return C.apply(bVal).get();
            }

            private Function<String, Supplier<String>> C = cVal -> new Supplier<String>() {
                @Override
                public String get() {
                    return cVal;
                }
            };
        };
    };
}

Stacktrace

An exception has occurred in the compiler (1.8.0_211). Please file a bug against the Java compiler via the Java bug reporting page (http://bugrepor
t.java.com) after checking the Bug Database (http://bugs.java.com) for duplicates. Include your program and the following diagnostic in your report
. Thank you.
java.lang.NullPointerException
        at com.sun.tools.javac.jvm.Code.emitop0(Code.java:559)
        at com.sun.tools.javac.jvm.Items$SelfItem.load(Items.java:367)
        at com.sun.tools.javac.jvm.Gen.genArgs(Gen.java:966)
        at com.sun.tools.javac.jvm.Gen.visitApply(Gen.java:1842)
        at com.sun.tools.javac.tree.JCTree$JCMethodInvocation.accept(JCTree.java:1465)
        at com.sun.tools.javac.jvm.Gen.genExpr(Gen.java:947)
        at com.sun.tools.javac.jvm.Gen.visitAssign(Gen.java:1982)
        at com.sun.tools.javac.tree.JCTree$JCAssign.accept(JCTree.java:1686)
        at com.sun.tools.javac.jvm.Gen.genExpr(Gen.java:947)
        at com.sun.tools.javac.jvm.Gen.visitExec(Gen.java:1781)
        at com.sun.tools.javac.tree.JCTree$JCExpressionStatement.accept(JCTree.java:1296)
        at com.sun.tools.javac.jvm.Gen.genDef(Gen.java:737)
        at com.sun.tools.javac.jvm.Gen.genStat(Gen.java:772)
        at com.sun.tools.javac.jvm.Gen.genStat(Gen.java:758)
        at com.sun.tools.javac.jvm.Gen.genStats(Gen.java:809)
        at com.sun.tools.javac.jvm.Gen.visitBlock(Gen.java:1157)
        at com.sun.tools.javac.tree.JCTree$JCBlock.accept(JCTree.java:909)
        at com.sun.tools.javac.jvm.Gen.genDef(Gen.java:737)
        at com.sun.tools.javac.jvm.Gen.genStat(Gen.java:772)
        at com.sun.tools.javac.jvm.Gen.genMethod(Gen.java:1031)
        at com.sun.tools.javac.jvm.Gen.visitMethodDef(Gen.java:994)
        at com.sun.tools.javac.tree.JCTree$JCMethodDecl.accept(JCTree.java:778)
        at com.sun.tools.javac.jvm.Gen.genDef(Gen.java:737)
        at com.sun.tools.javac.jvm.Gen.genClass(Gen.java:2454)
        at com.sun.tools.javac.main.JavaCompiler.genCode(JavaCompiler.java:745)
        at com.sun.tools.javac.main.JavaCompiler.generate(JavaCompiler.java:1572)
        at com.sun.tools.javac.main.JavaCompiler.generate(JavaCompiler.java:1536)
        at com.sun.tools.javac.main.JavaCompiler.compile2(JavaCompiler.java:901)
        at com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:860)
        at com.sun.tools.javac.main.Main.compile(Main.java:523)
        at com.sun.tools.javac.api.JavacTaskImpl.doCall(JavacTaskImpl.java:129)
        at com.sun.tools.javac.api.JavacTaskImpl.call(JavacTaskImpl.java:138)
        at org.codehaus.plexus.compiler.javac.JavaxToolsCompiler.compileInProcess(JavaxToolsCompiler.java:125)
        at org.codehaus.plexus.compiler.javac.JavacCompiler.performCompile(JavacCompiler.java:171)
        at org.apache.maven.plugin.compiler.AbstractCompilerMojo.execute(AbstractCompilerMojo.java:886)
        at org.apache.maven.plugin.compiler.CompilerMojo.execute(CompilerMojo.java:129)
        at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:134)
        at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:208)
        at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:154)
        at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:146)
        at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:117)
        at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:81)
        at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build(SingleThreadedBuilder.java:51)
        at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:128)
        at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:309)
        at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:194)
        at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:107)
        at org.apache.maven.cli.MavenCli.execute(MavenCli.java:955)
        at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:290)
        at org.apache.maven.cli.MavenCli.main(MavenCli.java:194)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:289)
        at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:229)
        at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:415)
        at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:356)

Tests

I did several attempts with different version(1.8.111, 1.8.152, 1.8.162, 1.8.211) and on different environment(Windows, Mac).

I tried with CMD using mvn clean compile or via intelliJ using maven plugin.

Removing function C all works fine.


My suppositions

hypothesis 1 This is a Java 8 limit and IntelliJ has a bug that allow me to collapse anonymous classes into lambdas though java 8 can't handle them.

hypothesis 2 This is a Java 8 bug.

I ask for your help for this interesting java problems. Thanks :)


UPDATE

I've opened a bug on Java Bug Database. I've the confirm that this is a bug and it has been resolved on later version 9, 10, 11, etc...

https://bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-8225771

Gorgonian answered 12/6, 2019 at 15:55 Comment(1)
I would say that your second hypothesis is correct given that the backtrace explicitly says to "file a bug." javac should never crash.Comparison
G
10

It is a Java compiler bug1. I can reproduce it with javac version 1.8.0_212 run from the command line. (No IDE's were used ... or harmed.)

The bug is not present in javac version 10.0.1, so upgrading your toolchain to Java 11 will fix the problem.


1 - Anything that causes the compiler to crash with an NPE is a bug!

Gujranwala answered 12/6, 2019 at 16:8 Comment(2)
Unfortunately i can't migrate the system to Java 10 or 11, i was afraid it was a bug...i don't understand why they have decided to fix it only in later versions, is it perhaps a lambda conversion's core design problem ?Gorgonian
You will need to simplify your code, or rewrite it to use nested classes instead of lambdas. (I am not going to speculate as to why the Java developers have not backported the bug fix.)Gujranwala

© 2022 - 2024 — McMap. All rights reserved.