加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

是否提取到Java优化所需的静态最终版本?

发布时间:2020-12-15 01:03:54 所属栏目:Java 来源:网络整理
导读:考虑这种方法: private void iterate(List 如您所见,该集正在创建一个带有自定义比较器的新TreeSet. 我想知道它是否与性能/内存/垃圾收集/任何观点有任何区别,如果我这样做而是污染了外层空间: static final Comparator 我问的原因是,我觉得编译器应该已经

考虑这种方法:

private void iterate(List

如您所见,该集正在创建一个带有自定义比较器的新TreeSet.

我想知道它是否与性能/内存/垃圾收集/任何观点有任何区别,如果我这样做而是污染了外层空间:

static final Comparator

我问的原因是,我觉得编译器应该已经解决了这个并为我优化它,所以我不应该提取它,对吧?

对于在方法中声明的字符串或其他临时不可变对象,情况也是如此.

提取最终变量会有什么不同吗?

注意:我知道这可能给性能提升带来的影响很小.问题是,是否存在任何差异,无论多么微不足道.

最佳答案
肯定会有所不同.

> CPU影响:分配静态可减少每次分配新比较器所需的工作量
> GC效果:每次分配一个新对象,然后立即丢弃它将没有年轻的GC成本;然而,将其分配给变量会增加GC时间(非常非常小),因为它是需要走的额外参考集.死对象没有任何成本,活对象也没有.
>内存效应:将比较器分配给常量将减少每次调用方法所需的内存量,以换取将被移入终端GC空间的低常量开销.
>引用转义的风险:内部类包含指向构造它的类的指针.如果内部类(Comparator)从创建它的方法中返回,那么对父对象的强引用可以转义并阻止父类的GC.纯粹是一个可以进入代码的陷阱,在这个例子中不是问题.

Hotspot非常擅长内联,但不太可能认识到比较器可以在堆上分配或移动到常量.但这取决于TreeSet的内容.如果TreeSet的实现非常简单(和小),那么它可以内联,但是我们都知道它不是. TreeSet也被编码为通用的,如果它只用于一种类型的对象(Worker),那么JVM可以应用一些优化但是我们应该假设TreeSet也会被其他类型使用,所以TreeSet不会能够对正在过去的比较器做出任何假设.

因此,两个版本之间的差异主要是对象分配.使用final关键字不太可能提高性能,因为Hotspot无论如何都会忽略final关键字.

使用lambda时,Java 8在这里有一个非常有趣的行为.请考虑以下示例的变体:

import java.util.*;

public class T {
    public void iterate(List

运行’javap -c T.class’,您将看到以下jvm代码:

  public void iterate(java.util.List

这里要注意的很酷的事情是lambda没有对象构造. invokedynamic在第一次调用它时会有更高的成本,然后它会被有效地缓存.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读