I have problem with the Java compiler. I simplified my code to:
package a;
public class Base {
// compiles if this is made public or an int
protected Integer value = 0;
}
---
package b; // must be in a separate package
import a.Base;
public class Sub extends Base {
public void increment() {
System.out.println(super.value);
value++;
super.value = 1;
super.value = super.value + 1;
// this line crashes the compiler; the others all work
super.value++;
}
}
after compiling I'm getting:
Information:java: An exception has occurred in the compiler (1.8.0_51). Please file a bug at the Java Developer Connection (http://java.sun.com/webapps/bugreport) after checking the Bug Parade for duplicates. Include your program and the following diagnostic in your report. Thank you.
Information:java: java.lang.NullPointerException
Information:java: at com.sun.tools.javac.code.Symbol$ClassSymbol.isSubClass(Symbol.java:1020)
Information:java: at com.sun.tools.javac.comp.Lower.accessClass(Lower.java:1108)
Information:java: at com.sun.tools.javac.comp.Lower.accessSymbol(Lower.java:983)
Information:java: at com.sun.tools.javac.comp.Lower.access(Lower.java:1220)
Information:java: at com.sun.tools.javac.comp.Lower.visitSelect(Lower.java:3855)
Information:java: at com.sun.tools.javac.tree.JCTree$JCFieldAccess.accept(JCTree.java:1897)
Information:java: at com.sun.tools.javac.tree.TreeTranslator.translate(TreeTranslator.java:58)
Information:java: at com.sun.tools.javac.comp.Lower.translate(Lower.java:2371)
Information:java: at com.sun.tools.javac.comp.Lower.translate(Lower.java:2382)
Information:java: at com.sun.tools.javac.comp.Lower.visitVarDef(Lower.java:3547)
Information:java: at com.sun.tools.javac.tree.JCTree$JCVariableDecl.accept(JCTree.java:852)
Information:java: at com.sun.tools.javac.tree.TreeTranslator.translateVarDefs(TreeTranslator.java:78)
Information:java: at com.sun.tools.javac.comp.Lower.visitLetExpr(Lower.java:3859)
Information:java: at com.sun.tools.javac.tree.JCTree$LetExpr.accept(JCTree.java:2426)
Information:java: at com.sun.tools.javac.comp.Lower.visitLetExpr(Lower.java:3860)
Information:java: at com.sun.tools.javac.comp.Lower.visitUnary(Lower.java:3319)
Information:java: at com.sun.tools.javac.tree.JCTree$JCUnary.accept(JCTree.java:1746)
Information:java: at com.sun.tools.javac.tree.TreeTranslator.visitExec(TreeTranslator.java:245)
Information:java: at com.sun.tools.javac.tree.JCTree$JCExpressionStatement.accept(JCTree.java:1296)
Information:java: at com.sun.tools.javac.tree.TreeTranslator.translate(TreeTranslator.java:70)
Information:java: at com.sun.tools.javac.tree.TreeTranslator.visitBlock(TreeTranslator.java:162)
Information:java: at com.sun.tools.javac.comp.Lower.visitBlock(Lower.java:3561)
Information:java: at com.sun.tools.javac.tree.JCTree$JCBlock.accept(JCTree.java:909)
Information:java: at com.sun.tools.javac.tree.TreeTranslator.visitMethodDef(TreeTranslator.java:145)
Information:java: at com.sun.tools.javac.comp.Lower.visitMethodDefInternal(Lower.java:2828)
Information:java: at com.sun.tools.javac.comp.Lower.visitMethodDef(Lower.java:2737)
Information:java: at com.sun.tools.javac.tree.JCTree$JCMethodDecl.accept(JCTree.java:778)
Information:java: at com.sun.tools.javac.comp.Lower.visitClassDef(Lower.java:2508)
Information:java: at com.sun.tools.javac.tree.JCTree$JCClassDecl.accept(JCTree.java:693)
Information:java: at com.sun.tools.javac.comp.Lower.translate(Lower.java:2390)
Information:java: at com.sun.tools.javac.comp.Lower.translateTopLevelClass(Lower.java:3932)
Information:java: at com.sun.tools.javac.main.JavaCompiler.desugar(JavaCompiler.java:1512)
Information:java: at com.sun.tools.javac.main.JavaCompiler.desugar(JavaCompiler.java:1356)
Information:java: at com.sun.tools.javac.main.JavaCompiler.compile2(JavaCompiler.java:901)
Information:java: at com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:860)
Information:java: at com.sun.tools.javac.main.Main.compile(Main.java:523)
Information:java: at com.sun.tools.javac.api.JavacTaskImpl.doCall(JavacTaskImpl.java:129)
Information:java: at com.sun.tools.javac.api.JavacTaskImpl.call(JavacTaskImpl.java:138)
Information:java: at org.jetbrains.jps.javac.JavacMain.compile(JavacMain.java:168)
Information:java: at org.jetbrains.jps.incremental.java.JavaBuilder.compileJava(JavaBuilder.java:382)
Information:java: at org.jetbrains.jps.incremental.java.JavaBuilder.compile(JavaBuilder.java:296)
Information:java: at org.jetbrains.jps.incremental.java.JavaBuilder.doBuild(JavaBuilder.java:204)
Information:java: at org.jetbrains.jps.incremental.java.JavaBuilder.build(JavaBuilder.java:176)
Information:java: at org.jetbrains.jps.incremental.IncProjectBuilder.runModuleLevelBuilders(IncProjectBuilder.java:1202)
Information:java: at org.jetbrains.jps.incremental.IncProjectBuilder.runBuildersForChunk(IncProjectBuilder.java:877)
Information:java: at org.jetbrains.jps.incremental.IncProjectBuilder.buildTargetsChunk(IncProjectBuilder.java:948)
Information:java: at org.jetbrains.jps.incremental.IncProjectBuilder.buildChunkIfAffected(IncProjectBuilder.java:840)
Information:java: at org.jetbrains.jps.incremental.IncProjectBuilder.buildChunks(IncProjectBuilder.java:665)
Information:java: at org.jetbrains.jps.incremental.IncProjectBuilder.runBuild(IncProjectBuilder.java:372)
Information:java: at org.jetbrains.jps.incremental.IncProjectBuilder.build(IncProjectBuilder.java:193)
Information:java: at org.jetbrains.jps.cmdline.BuildRunner.runBuild(BuildRunner.java:137)
Information:java: at org.jetbrains.jps.cmdline.BuildSession.runBuild(BuildSession.java:293)
Information:java: at org.jetbrains.jps.cmdline.BuildSession.run(BuildSession.java:124)
Information:java: at org.jetbrains.jps.cmdline.BuildMain$MyMessageHandler$1.run(BuildMain.java:242)
Information:java: at org.jetbrains.jps.service.impl.SharedThreadPoolImpl$1.run(SharedThreadPoolImpl.java:41)
Information:java: at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
Information:java: at java.util.concurrent.FutureTask.run(FutureTask.java:266)
Information:java: at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
Information:java: at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
Information:java: at java.lang.Thread.run(Thread.java:745)
Information:java: Errors occurred while compiling module 'testAGH'
Information:2015-10-23 14:23 - Compilation completed with 1 error and 0 warnings in 671ms
Error:java: Compilation failed: internal java compiler error
Why does Java fail to compile this?
This is clearly a compiler bug. You should file a bug as the output instructs, but since you asked why I'll try to explore that :)
The JDK langtools repo contains the code for javac
. I browsed through several different builds but wasn't able to find a version with line numbers that matched up with the stack trace (I'm not sure how to match a Java version to a build number), so I'm going off of the most recent build, b132.
As you can see, the underlying issue is a NullPointerException
in com.sun.tools.javac.code.Symbol
in Symbol.ClassSymbol.isSubClass()
. So that's the source of the issue. Looking higher in the stack trace we can see access()
calls accessSymbol()
then accessClass()
before reaching isSubClass()
. So we can infer that the compiler is trying to verify the subclass is permitted to access super.value
at the time it fails.
Without knowing which line the NPE is occurring on it's hard to pinpoint the exact problem, so unfortunately here things get fuzzy. Since this failure only occurs when we try to increment-and-set (++
or +=
) the field, and only if we refer to it as super.value
, we'd expect to see some code related to casting, autoboxing, assignment, or arithmetic. Alas nothing in isSubClass()
really seems related to any of that.
My guess, given that there doesn't appear to be anything incriminating in isSubClass()
, is that Lower.accessClass()
is passing a null
into isSubClass()
. There are three values passed to isSubClass()
in this method: the field currentClass
(as c
, this is "the currently enclosing class"), sym.owner
(I think sym
is our value
field, I don't know what its owner
is but presumably the class it's declared in), and types
, which looks to always be set to a non-null value. So it's either currentClass
or sym.owner
, and there are references to sym.owner
that would NPE in Lower.access()
earlier, so that also seems to be non-null.
So I'll hazard that the culprit is Lower.currentClass
is null for some reason. Since currentClass
is a package-private non-final field, I'm not going to bother trying to determine if it can be null
at this time or not, but it appears possible. There are several other possible culprits in isSubClass()
of course, so I could well be wrong.
Inconclusive, but I hope this was informative! I'll certainly update if I learn more.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With