Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java compiler fails when compiling simple program

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?

like image 877
Yozer Avatar asked Oct 23 '15 12:10

Yozer


1 Answers

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.

like image 116
dimo414 Avatar answered Oct 12 '22 23:10

dimo414