慢JDK8编译

尝试在一个大项目上升级到JDK8,与JDK7相比,JDK8上的编译速度非常慢。

以详细模式运行编译器,JDK8编译器停止在从服务器到客户端的实体的大生成转换器类(映射)。 在几种情况下,转换器方法从同一Mapping类调用其他转换器方法。

作为一种解决方法,尝试将Mapping文件拆分为多个文件。 仅在编译Mapping类或包含项目(projectA)时,这显着提高了性能。 但是对于从projectA调用转换器方法的其他项目,编译时间非常慢。

另一个解决方法是使所有转换方法返回null,而不是调用任何其他方法。 同样,性能对projectA有利,但不适用于依赖项目。

ProjectA使用generics,但由于它与JDK6兼容,后者没有引入广义类型推断,可能是另一个导致这种减速的JDK8错误。

因此可能脱离上下文但是对于通用类型推断,下面的一些线程建议升级到JDK9。 但由于它尚未发布,因此升级并不是一个可行的选择。 如果修复程序的后端移植到JDK8,那将是理想的选择。 这是在以下StackOverflow线程中请求的,但尚未得到Oracle团队的回复。

使用jOOQ 3.6 +,纯SQL和javac编译器进行慢速编译

我附上了两个关于堆在JDK7和JDK8中的外观截图。 这可能是导致JDK8放缓的原因吗?

谢谢!

更新20160314

Mapping类的转换器方法如下所示:

public static ResponseItemVO convert (ResponseItem pArg0){ if(pArg0==null){ return null; } ResponseItemVO ret = new ResponseItemVO(); ret.setErrorDetails(pArg0.getErrorDetails()); ret.setResult(Mapping.convert(pArg0.getResult())); ret.setIdentifier(Mapping.convert(pArg0.getIdentifier())); return ret; } 

VO看起来像:

 public class ResponseItemVO extends ResultVO { public ResponseItemVO() {} } 

JDK7堆: JDK7堆 JDK8堆: JDK8堆

您已经注意到,当基于通用目标类型的重载解析时,Java 8中存在严重的性能回归 。 您的情况中的一个原因可能是编译器需要从赋值类型中找到适当的方法

 ResultVO result = Mapping.convert(...); // heavy lookup here ---------------------------^^^^^^^ 

如果您控制代码生成器,而不受向后兼容性的限制,那么可能值得考虑避免convert()方法的重载。 在没有重载的情况下,编译器不必在映射代码内部或调用站点上执行重载解析工作。 这肯定会快得多。

尝试1:通过在方法名称中使用参数类型:

 class Mapping { public static ResponseItemVO convertResponseItem(ResponseItem pArg0){ if (pArg0==null){ return null; } ResponseItemVO ret = new ResponseItemVO(); ret.setErrorDetails(pArg0.getErrorDetails()); ret.setResult(Mapping.convertResult(pArg0.getResult())); ret.setIdentifier(Mapping.convertIdentifier(pArg0.getIdentifier())); return ret; } } 

尝试2:将转换方法移动到其他位置,例如转换为VO类型

 class ResponseItemVO { public static ResponseItemVO from(ResponseItem pArg0){ if (pArg0==null){ return null; } ResponseItemVO ret = new ResponseItemVO(); ret.setErrorDetails(pArg0.getErrorDetails()); ret.setResult(ResultVO.from(pArg0.getResult())); ret.setIdentifier(IdentifierVO.from(pArg0.getIdentifier())); return ret; } } 

或更好…

 class ResponseItem { public ResponseItemVO toVO(){ ResponseItemVO ret = new ResponseItemVO(); ret.setErrorDetails(getErrorDetails()); ret.setResult(getResult().toVO()); ret.setIdentifier(getIdentifier().toVO()); return ret; } }