我们javac
以注解的形式为编译器实现了一些超魔力Processor
。使用一些看似无辜的 java 源文件,我们会得到以下自相矛盾的错误消息:
[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 是我们正在尝试处理的注解的名称,但错误发生在其他一些类中,行号与正在处理的注解无关。注释处理器将 a 应用于TreeTranslator
注释类的 AST,从而重写 AST 本身。
如果我们直接调用ant
或调用javac
,错误就会消失,并且注释处理器在 Linux 下似乎可以正常工作。在 Windows 下,第二次编译没有帮助,我们再次得到错误。当然,如果我们ant clean
手动删除输出目录,即使在 Linux 上也会再次抛出错误。
JDK 1.7 和 1.6 都会出现以下错误消息(当然,注释处理器是使用相应的 tools.jar 编译的)。
看起来好像 javac 的类文件检查器认为那java
是类,但绝对不是。我们项目的类路径中根本没有这样的类名,而且我们无处依赖它。不幸的是,该类在检查失败后并没有被写入文件系统,因此我们可以检查 - 可能严重损坏的 - 类文件。
什么可能导致如此令人费解的编译器错误?有没有办法在编译后检查失败的类文件并解开这个谜团?
我们设法将问题缩小到以下几点:
有一个类,say Wtf
,它包含一个 switch 语句切换枚举(参见https://stackoverflow.com/a/4319152/560450)或其他一些匿名内部类。如果类,比如说AA
,,,BB
和继承自CC
并包含至少一个方法(似乎跳过检查空类),并且注释处理器生成的AST部分包含对其他东西的引用,那么,和,即除了字典顺序之外的所有后代都会产生错误。原因可能是与加载内部类和解析对DD
Wtf
javac
java.lang.Object
java.lang
BB
CC
DD
javac
java.lang
,或其他一些曲折的小方法调用,都一样。