慢JDK8编译

时间:2016-03-14 15:14:23

标签: java compilation java-8 compiler-optimization

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

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

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

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

ProjectA使用泛型但由于它与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

1 个答案:

答案 0 :(得分:2)

在基于通用目标类型的重载解析时,您已经注意到了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;
    }
}