I maintain a fast online Java compilation and execution engine named Jeed that we use to support a playground for my course on introductory programming.
Jeed is actually implemented in Kotlin and I’d like to start teaching in Kotlin at some point in the near future. So I’ve started working on getting in-memory compilation of Kotlin snippets to work. That is going pretty well so far…
…except that I realized that something I had changed had caused all of my Java compilation tests to fail. Turns out it was just adding:
implementation(kotlin("compiler"))
to my build.gradle.kts
file. That causes the javax.tools
compiler to fail with the following error message:
An exception has occurred in the compiler (10.0.1). Please file a bug against the Java compiler via the Java bug reporting page (http://bugreport.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 jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment$1.visitTopLevel(JavacProcessingEnvironment.java:1528)
at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCCompilationUnit.accept(JCTree.java:529)
at jdk.compiler/com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49)
at jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment$1.scan(JavacProcessingEnvironment.java:1512)
at jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment$Round.newRound(JavacProcessingEnvironment.java:1251)
at jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment$Round.<init>(JavacProcessingEnvironment.java:1051)
at jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment$Round.next(JavacProcessingEnvironment.java:1090)
at jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment.doProcessing(JavacProcessingEnvironment.java:1322)
at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.processAnnotations(JavaCompiler.java:1250)
at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:928)
at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.lambda$doCall$0(JavacTaskImpl.java:100)
at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.handleExceptions(JavacTaskImpl.java:142)
at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.doCall(JavacTaskImpl.java:96)
at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.call(JavacTaskImpl.java:90)
at edu.illinois.cs.cs125.jeed.core.CompileKt.compile(Compile.kt:78)
at edu.illinois.cs.cs125.jeed.core.CompileKt.compile$default(Compile.kt:57)
at edu.illinois.cs.cs125.jeed.core.CompileKt.compile(Compile.kt:107)
at edu.illinois.cs.cs125.jeed.core.CompileKt.compile$default(Compile.kt:105)
at edu.illinois.cs.cs125.jeed.core.TestCompile$1$4.invokeSuspend(TestCompile.kt:41)
at edu.illinois.cs.cs125.jeed.core.TestCompile$1$4.invoke(TestCompile.kt)
at io.kotlintest.runner.jvm.TestCaseExecutor$executeTest$supervisorJob$1$invokeSuspend$$inlined$map$lambda$1.invokeSuspend(TestCaseExecutor.kt:133)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(Dispatched.kt:233)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1135)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
at java.base/java.lang.Thread.run(Thread.java:844)
The error occurs here in JavacProcessingEnvironment.java:1528
:
boolean isModuleInfo = node.sourcefile.isNameCompatible("module-info", Kind.SOURCE);
if (isModuleInfo) {
node.modle.reset();
node.modle.completer = sym -> modules.enter(List.of(node), node.modle.module_info);
node.modle.module_info.reset(); // This causes a NPE
node.modle.module_info.members_field = WriteableScope.create(node.modle.module_info);
}
I’ve extended the FileManager
used by the javax.tools
compiler to support memory-backed file objects but also forward other requests to the system file manager. I’ve added some instrumentation there and it looks like something about just importing the Kotlin compiler library modifies the Java environment in such a way that causes Java compilation to fail. The failure seems to occur where the compiler would normally be enumerating the java.io modules, but that’s all I’ve had time to figure out at this point.
The current master
branch in the Jeed repository should be able to reproduce the problem. Just add the implementation(kotlin("compiler"))
line to core/build.gradle.kts
and rerun the tests in TestCompile.kt
.
Any pointers would be appreciated—even if it’s just to what part of the compiler package is messing with the Java environment.