jdk 8u91一个lambda类型推断的bug
公司内部发布maven包是在公司构建服务器上编译的。最近一次上线,发现同样的代码,在本地的jdk8上能编译通过,但是在构建服务器上,就编译报错。
简化后的代码如下:
1 | import java.util.Optional; |
1 | public interface RetryCallback<T, E extends Throwable> { |
用maven编译报错如下:
1 | JavaBugTest.java:[10,36] unreported exception E; must be caught or declared to be thrown |
最后发现,是构建服务器jdk版本太老导致的。
二分法尝试了几个版本,发现8u91不行,但是8u92就能编译通过了。
于是开始调试javac代码,发现两个版本的AST不一样:
可以看到,8u92以及之后的版本,作为Optional.ofNullable的参数,execute的异常能够被推断为RuntimeException,这一点是很正常的,因为我传进去的lambda本来就没有任何受检异常声明。
那么这个bug是怎么修复的呢?
这是从8u92修复的,所以可以查一下8u92的发布说明,里面提到了这个bug JDK-8066974 : Compiler doesn’t infer method’s generic type information in lambda body 。
修复代码如下:
简而言之,就是分析到ofNullable
的时候,添加一个回调,等到内部的lambda类型推断完成后,再将这儿的类型修改掉(就是E
改成了RuntimeException
)。
P.S. JDK 8u91版本没有附带javac的源码,需要手动下载,并在IDEA配置好源码路径才能调试:
jdk 8u91一个lambda类型推断的bug
https://robberphex.com/a-bug-about-lambda-type-infer-on-jdk-8u91/