由于 JDK 错误,我设法编写了一些在使用 JDK 1.8.0_131 进行编译期间导致错误的代码。我只需要几行代码就可以重现这个问题——但我找不到在我的项目中的哪个位置使用了导致错误的模式。
我的目标是找出我的项目中的哪些代码导致了这个错误,并应用了解决方法。
问题和复制
该问题在JDK-8074381 错误报告中进行了概述,并且只需几行代码即可复制。
public class Test {
public interface Foo<L> extends Function<Number, String> {
String apply(Number p);
}
private static final Foo CRASH = p -> "This will crash javac 1.8.0_131";
}
当使用非参数化的 lambda 而不是非参数化的内部类(根据我相信的语言规范,这两者都应该是有效的)时,这个问题就会显现出来。所以
private static final Foo INNER = new Foo<Object>() {
@Override
public String apply(final Number p) {
return "This will not crash javac 1.8.0_131";
}
};
工作正常。有问题的堆栈跟踪开始(为了您的理智而截断):
An exception has occurred in the compiler (1.8.0_131). 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.AssertionError
at com.sun.tools.javac.util.Assert.error(Assert.java:126)
at com.sun.tools.javac.util.Assert.check(Assert.java:45)
at com.sun.tools.javac.code.Types.functionalInterfaceBridges(Types.java:659)
at com.sun.tools.javac.comp.LambdaToMethod$LambdaAnalyzerPreprocessor$TranslationContext.<init>(LambdaToMethod.java:1770)
at com.sun.tools.javac.comp.LambdaToMethod$LambdaAnalyzerPreprocessor$LambdaTranslationContext.<init>(LambdaToMethod.java:1853)
at com.sun.tools.javac.comp.LambdaToMethod$LambdaAnalyzerPreprocessor.analyzeLambda(LambdaToMethod.java:1337)
at com.sun.tools.javac.comp.LambdaToMethod$LambdaAnalyzerPreprocessor.visitLambda(LambdaToMethod.java:1322)
at com.sun.tools.javac.tree.JCTree$JCLambda.accept(JCTree.java:1624)
at com.sun.tools.javac.tree.TreeTranslator.translate(TreeTranslator.java:58)
at com.sun.tools.javac.tree.TreeTranslator.visitVarDef(TreeTranslator.java:153)
鉴别
我知道这个问题在 JDK9 中得到修复,但是这个项目要求我使用 JDK 8。
因此,我不需要更新到 JDK9,而是需要找出该项目中的哪些代码产生了错误。这是我尝试过的。
我的第一个想法是检查发生此错误时正在编译的文件。但是,我无法弄清楚在遇到错误时如何检查正在编译的源文件。如果这是可能的,那么该信息将很有帮助。
我的第二个想法是对我的所有代码进行正则表达式搜索,以查找任何类型参数化接口或扩展通用接口的接口。这些搜索都没有产生明显匹配问题产生代码的代码——没有未使用的泛型(在示例中更改
interface Foo<L>
为interface Foo
可以解决问题)。因此,我认为对编译器内部实际导致此错误的原因进行更微妙的了解可能有助于确定负责的代码段,因为它可能会扩大我的搜索标准。(对于完全不同的问题,我也有可能遇到具有完全相同堆栈跟踪的错误,但这对我来说似乎不太可能,我不确定从哪里开始,有什么想法吗?)
我认为最值得检查编译器日志或其他东西来检查这个问题出现时正在编译的内容。有任何想法吗?
谢谢。