【问题标题】:JDK compiler optimize use of anonymous classes with no instance variables?JDK编译器优化了没有实例变量的匿名类的使用?
【发布时间】:2011-09-17 09:03:39
【问题描述】:

我很好奇,我经常看到这种东西:

Arrays.sort(array, new Comparator<Integer>() {
    public int compare(Integer a, Integer b) {
        return Math.abs(a) < Math.abs(b);
    }
});

由于这里创建的匿名类没有实例变量,标准 JDK 编译器是否足够聪明,只实例化该匿名类一次并重用它?还是建议在静态字段中实例化该匿名类并始终传递静态 Comparator 对象?

更新:当我说“JDK 编译器”时,我指的是 JIT 部分。以上也只是一个例子。我真的很好奇我是否应该作为最佳实践为上述创建静态字段而不是内联匿名类实例化。在某些情况下,性能/资源使用问题可以忽略不计。但其他情况可能不是……

【问题讨论】:

    标签: java comparator anonymous-class


    【解决方案1】:

    javac 肯定不会做这种事;这将违反语言语义。 JVM理论上可以优化它,但还没有那么聪明。静态的会更快。

    具有讽刺意味的是,这样的分析和优化对于 javac 来说是很容易的,而且今天也可以做到,只是禁止这样做——消息来源说 new,所以 javac 必须 new

    有传言称,Java 8 中即将到来的 lambda 表达式将在这个问题上做出努力,在

    Arrays.sort(array, (Integer a,Integer b) => Math.abs(a)<Math.abs(b) )
    

    需要javac来分析lambda是无状态的,懒惰创建的单个实例就足够了,这就是它必须将代码编译成的。

    【讨论】:

      【解决方案2】:

      答案是可能的。

      javac 会将其编译成与您的代码相符的字节码。因此,每次调用此代码时,都会重新实例化该类。然而,JVM 在运行时执行了许多复杂的优化,并且可能 - 取决于许多因素 - 在这里执行一些优化。

      无论如何,除非您注意到此处存在真正的性能问题,否则我建议您不要尝试手动优化。

      【讨论】:

        【解决方案3】:

        你可以使用javap来检查自己;我怀疑它会在每次通话时创建它。这种优化由热点处理,但在这种情况下,由于匿名只有方法(没有要初始化的字段),开销非常小。

        【讨论】:

          【解决方案4】:

          这里真正的问题不是javac 会做什么。正如 Steve McLeod 所说,javac 将生成与您的源代码匹配的字节码。问题是 hotspot 在运行时会做什么。我想它会简单地内联所有内容(包括Math.abs() 调用)。

          【讨论】:

            【解决方案5】:

            编译器做的优化很少。 jit 完成了大部分工作。它将优化此代码,但不会避免创建 Integer 对象,除非您有 Integer 数组,否则这将是您的瓶颈。如此之多,以至于它所做的任何其他优化都无关紧要。

            【讨论】:

              猜你喜欢
              • 2011-03-19
              • 1970-01-01
              • 2016-10-12
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多