是否有专门的可选类型(OptionalInt,OptionalDouble等)执行堆分配?

时间:2015-10-21 20:09:31

标签: java java-8

返回专门的可选类型的调用函数是否以在热代码路径中使用时增加GC压力为代价,而不是返回原始值以指示缺席(例如Integer.MIN_VALUE)?

修改

我不认为他们会像其他任何类一样执行堆分配的原因是Optional等等," value-based classes"似乎暗示他们的行为可能与幕后的传统课程不同。

2 个答案:

答案 0 :(得分:6)

  

返回专门的可选类型的调用函数是否以在热代码路径中使用时增加的GC压力为代价

取决于™。 通常 Optional类型只是常规对象,因此堆已分配。但在特定情况下,JIT编译器可以将它们分解为它们的字段(即它们保存的值)并将它们放在堆栈中。

如果escape analysis可以确定对象没有全局转义到堆上,则会发生这种情况。

似乎还有一些隐藏在标志后面的实验性优化(-XX:+AggressiveUnboxing-XX:+AggressiveOpts的一部分)。据我了解,他们可以打破Integer.valueOf(int)的身份保证,因此不完全符合规范。

切线:实验/研究Graal compiler甚至更进一步,并且partial escape analysis可以将分配推迟到那些对象确实转义的代码路径,同时在堆栈中将它们标量分解别。这还不是常规虚拟机的一部分,主要用于在JVM上运行的非java语言,例如JRuby和Nashorn。

由于所有这些都是运行时优化,因此无法保证会发生这种情况。因此,您必须使用诊断标志来衡量效果或跟踪编译器决策。

  

我不仅仅假设他们会像任何其他类一样执行堆分配的原因是Optional,et al,是“基于价值的类”

我认为目前这些属性只是为了确保对象是不可变的和线程安全的。我不知道EA之外的任何优化是否都使用了互换性属性。

我怀疑规范语言主要是为了在最终作为value-types的一部分到达Java时提供正确的project valhalla的前向兼容性。

遵循这些规则还可以使转义分析/堆栈分配更容易。

答案 1 :(得分:4)

这些类扩展Object,因此是引用类型。它们将占用堆空间,类似于使用以前可用的包装类(如Integer)。

此外,这些类型鼓励使用lambda表达式,它们自己创建匿名类型的新实例。根据lambdas"关闭"的值,您最终可能会引用那些引用其他对象的对象,这会对GC产生一些影响。

因此,在您希望避免实例化类,装箱/拆箱等实例的地方,出于性能原因,您仍然希望避免使用这些可选类型。

更新

Java 8引入了基于价值的类的概念,作为Java 10"价值类型的有希望的垫脚石。"

  

InfoQ:让我们谈谈Optional作为原始值类型的可能性。

     

Goetz:将Java 8引用类型迁移到Java 10值类型的想法可能略微乐观一些。基本上,我们已经奠定了基础,表明开发人员不得依赖某些属性(例如身份检查),对于未来可能成为价值类型的类型而言必然如此。这种迁移在实践中是否可行仍有待观察。

http://www.infoq.com/articles/Java-9-and-Beyond-Goetz-Rose-Interview

从Java 8开始,这些类仍然像普通类一样工作,但是现在通过对它们创建某些限制,有些人希望在Java 10获得该功能时可以将它们转换为值类型。

假设它最终发生,我认为将这些类型转换为值类型有两个主要优点:

  1. 提高了性能,因为您不需要使用堆空间。
  2. 值类型永远不会为null,因此如果您有一个OptionalDouble类型的字段并且您从未初始化它,那么您仍然不会获得空指针异常。
  3. 无耻的插件:我已经在C#中为我编写的库中的Maybe<>类型利用了结构类型的这些属性。