什么原因会导致热点编译器将一个方法分类为“不可编译(已禁用)”?

10

在对一个应用程序进行了一些更改后,它的性能显著下降,在调查后发现其中一个最频繁调用的方法不再被编译。打开:-XX:+LogCompilation 显示,在更改之前,此方法已经:排队等待编译、编译并成功内联到调用者; 然而在更改后,没有记录编译尝试的记录,并且内联尝试显示:

inline_fail reason='not compilable (disabled)'

原始方法如下所示,其中_maxRepeats是作为Map声明的实例变量(没有泛型,编写时间很久),使用时键是DadNode类的对象,值是Integer

  private int cnsGetMaxRepeats(DadNode dn) {
    if (_maxRepeats != null) {
      Integer max = (Integer)_maxRepeats.get(dn);
      if (max != null) {
        return max;
      }
    }
    return dn.getMaxOccurs().getValue();
  }
修改涉及将_maxRepeats map更改为使用泛型:
  Map<Integer, Integer>

并且该方法添加了一个新参数:

   private int cnsGetMaxRepeats(int childIdx, DadNode dn) {
    if (_maxRepeats != null) {
      Integer max = _maxRepeats.get(childIdx);
      if (max != null) {
        return max;
      }
    }
    return dn.getMaxOccurs().getValue();
  }

使用显式调用 Integer.valueOfInteger.intValue 来避免自动装箱不会有任何区别;该方法仍然无法编译。

我可以“用棍子戳它”直到我得到一个做我想做的事情(并且也可编译)的解决方案,但是这种禁用背后的标准是什么?


它可能因与代码本身无关的原因而被标记为不可编译。例如,您是否尝试增加代码缓存大小?-XX:ReservedCodeCacheSize - Gene
你正在使用哪个版本的Java?操作系统是32位还是64位?你正在使用客户端编译器还是服务器编译器? - Sean Mickey
你使用的是哪个版本?LogCompilation 长期以来一直是 PrintCompilation... - Eugene
1个回答

2

我认为我犯了一个基本错误——在通过IntelliJ进行调试时(尽管断点已静音),使用“禁用编译”方法生成的日志。我预计,即使静音,IntelliJ也会禁用具有断点的方法的编译。

所以回答我的问题,除了明确禁用编译之外,我没有理由认为任何其他事情会这样做。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接