JDK编译器优化使用没有实例变量的匿名类?
我很好奇,我经常看到这种事情:
Arrays.sort(array, new Comparator<Integer>() {
public int compare(Integer a, Integer b) {
return Math.abs(a) < Math.abs(b);
}
});
由于这里创建的匿名类没有实例变量,标准JDK编译器是否足够聪明,只实例化该匿名类一次并重用它?或者是否建议在静态字段中实例化该匿名类并始终传递静态 Comparator 对象?
更新:当我说“JDK编译器”时,我指的是JIT部分。以上也只是一个例子。我真的很好奇,作为最佳实践,我是否应该为上述内容创建静态字段,而不是内联匿名类实例化。在某些情况下,性能/资源使用问题可以忽略不计。但其他情况可能不会...
I was curious, I see this kind of thing a lot:
Arrays.sort(array, new Comparator<Integer>() {
public int compare(Integer a, Integer b) {
return Math.abs(a) < Math.abs(b);
}
});
since the anonymous class created here has no instance variables, is the standard JDK compiler smart enough to only instantiate that anonymous class once and reuse it? Or is it advisable to instantiate that anonymous class in a static field and always pass the static Comparator object?
UPDATE: When I say "JDK compiler", I mean the JIT portion too. The above is also just an example. I was really curious if I should, as a best practice, create static fields for the above instead of inlining anonymous class instantiations. In some cases the performance/resource usage issue will be negligible. But other cases might not be...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
javac 肯定不会做这样的事情;这会违反语言语义。理论上JVM可以优化它,但还没有那么聪明。静态的会更快。
讽刺的是,这样的分析和优化对于 javac 来说很容易,今天就可以完成,只是禁止这样做 - 消息来源说
new
,所以 javac 必须new
。有传言说java 8中即将到来的lambda表达式将在这个问题上做出努力,在
javac中需要分析lambda是无状态的,并且延迟创建的单个实例就足够了,这就是它必须将代码编译成的内容。
javac will definitely not do such thing; that would violate the language semantics. JVM could optimize it in theory, but it's not that smart yet. A static one would be faster.
Ironically, such analysis and optimization would be easy for javac, and it can be done today, except it's forbidden to do so - the source says
new
, so javac mustnew
.Rumor has it that the coming lambda expression in java 8 will make an effort on this issue, in
javac is required to analyze that the lambda is stateless, and a lazily created single instance is enough, and that's what it must compile the code into.
答案是也许。
javac 会将其编译成与您的代码相符的字节码。因此,每次调用此代码时都会重新实例化该类。然而,JVM 在运行时执行许多复杂的优化,并且可能 - 取决于许多因素 - 在这里执行一些优化。
无论如何,除非您注意到这里存在真正的性能问题,否则我建议不要尝试手动优化。
The answer is maybe.
javac will compile this into bytecode that is true to your code. Therefore, the class will be instantiate anew each time this code is called. However the JVM performs many sophisticated optimisations at runtime, and MIGHT - depending on many factors - perform some optimisations here.
In any case, unless you've noticed a real performance issue here, I'd recommend not trying to manually optimise.
你可以使用javap来检查一下自己;我怀疑它会在每次通话时创建它。此类优化由热点处理,但在这种情况下,由于匿名只有方法(没有要初始化的字段),因此开销非常小。
You can use javap to check yourself; my suspicion is that it will create it on every call. Such optimizations are handled by hotspot but in this case since the anonymous only has methods (no fields to initialize) the overhead is very small.
这里真正的问题不是 javac 将做什么。正如 Steve McLeod 所说,
javac
将生成与源代码匹配的字节码。问题是 hotspot 在运行时会做什么。我想它将简单地内联整个过程(包括 Math.abs() 调用)。The real question here is not what
javac
will do. As Steve McLeod says,javac
will produce bytecode which matches your source code. The question is what hotspot will do at runtime. I imagine it will simple inline the whole lot (including theMath.abs()
call).编译器几乎没有进行优化。 jit 完成了大部分工作。它会优化此代码,但不会避免创建 Integer 对象,除非您有一个 Integer 数组,否则这将是您的瓶颈。如此之多以至于它所做的任何其他优化都无关紧要。
The compiler does very little optimisation. The jit does most of it. It will optimise this code but it won't avoid creating Integer objects and unless you have an array of Integer this will be your bottle neck. So much so that any other optimisation it does won't matter.