We have implemented some metamagic for the javac
compiler in form of an annotation Processor
. With some innocent-looking java source files, we get the following paradoxical error message:
[javac] [checking org.dirty_ice.underscores.tower_defense.wave.HumanSpawner]
[javac] /home/kris/bme/tower_defense/src/game/org/dirty_ice/underscores/tower_defense/wave/HumanSpawner.java:9: cannot find symbol
[javac] symbol: class java
[javac] @Trace("spawner")
[javac] ^
@Trace is the name of the annotation we are trying to process, but the error occurs in some other classes, with line numbers unrelated to the annotation being processed. The annotation processors applies a TreeTranslator
to the AST of the annotated class, thus rewriting the AST itself.
If we invoke ant
or javac
directly, the error goes away the program and the annotation processor appears to function correctly under Linux. Under Windows, the second compilation does not help and we again get the error. Of course, the error is thrown again even on Linux if we ant clean
or manually delete the output directory.
The following error message appears with both JDK 1.7 and 1.6 (the annotation processor being compiled with the corresponding tools.jar, of course).
It appears as if javac's class file checker thinks that java
is class, which it is absolutely not. We have no such class name in our project's class path at all, and we nowhere depend on it. Unfortunately, the class does not get written to the filesystem after it fails checking, so that we could inspect the -- possibly badly mangled -- class file.
What could cause such a puzzling compiler error? Is there any way to inspect the failed class file after compilation and unravel this mystery?
We have managed to narrow the issue down to the following:
There is a class, say Wtf
, which contains an switch statement switching on an enum (see https://stackoverflow.com/a/4319152/560450) or some other anonymous inner class. If classes, say, AA
, BB
, CC
and DD
inherit from Wtf
and contain at least one method (javac
seems to skip checking for empty classes), and the parts of the AST generated by the annotation processor contain references to java.lang.Object
of something else from java.lang
, then BB
, CC
and DD
, i.e. all descendants but the lexicographically first will generate the error. The reason may possibly be some race condition inside javac
related to loading the inner class and resolving references to java.lang
, or some other twisty little method calls, all alike.