java - JDK8编译速度慢

标签 java compilation java-8 compiler-optimization

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

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

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

另一个解决方法是让所有转换方法返回 null,而不调用任何其他方法。同样,项目 A 的性能很好,但依赖项目的性能却不佳。

ProjectA 使用泛型,但由于它与 JDK6 兼容,而 JDK6 没有引入广义类型推断,因此可能是另一个 JDK8 错误导致了速度下降。

因此可能脱离上下文,但对于广义类型推断,像下面这样的一些线程建议升级到 JDK9。但由于它尚未发布,因此它不是一个可行的升级选项。 如果能够将修复程序向后移植到 JDK8,那就太理想了。这是在以下 StackOverflow 线程中提出的请求,但 Oracle 团队尚未回复。

Slow compilation with jOOQ 3.6+, plain SQL, and the javac compiler

我附上了两张 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<IdentifierVO, DetailsVO >  {
    public ResponseItemVO() {}
}

JDK7 堆: JDK7-heap JDK8 堆: JDK8-heap

最佳答案

您已经注意到了,there's a severe performance regression in Java 8当涉及到基于通用目标类型的重载决策时。您的情况的原因之一可能是编译器需要从赋值类型中找到适当的方法

ResultVO<Something, Something> 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;
    }
}

关于java - JDK8编译速度慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35991287/

相关文章:

java - Android XML 和 .java 文件中的最佳实践和约定

c++ - 应该如何设置王朝?

c++ - 找不到CoreAudio,AudioToolbox,AudioUnit等 header

java - 如何在 MacOS 上安装特定的 JDK(jdk1.8.0_152.jdk)?

java - 如何像grep一样从java 8流匹配前后获取行?

java - 如何扫描整个 C 盘的播放列表

java - 关于 BufferedImage.getSubimage(int x, int y, int w, int h) 方法的指导?

java - Wildfly Jboss NoClassDefFoundError : Failed to link Error for org/jboss/ws/core/jaxws/spi/ProviderImpl

assembly - 扩展编译器以获得自己的汇编输出

java - 映射列表并映射成 map