Java 专用可选类型(Optionant、OptionalDouble等)是否执行堆分配?

Java 专用可选类型(Optionant、OptionalDouble等)是否执行堆分配?,java,java-8,Java,Java 8,当在热代码路径中使用时,返回专用可选类型的调用函数是否会以增加GC压力为代价,而不是返回一个原语值来表示不存在(Integer.MIN_value) 编辑 我之所以不认为它们会像任何其他类一样执行堆分配,是因为Optional等是“”,这似乎意味着它们在幕后的行为可能与传统类不同。是的 这些类扩展了对象,因此是引用类型。它们将占用堆空间,这与使用以前可用的包装器类(如Integer)类似 此外,这些类型鼓励使用lambda表达式,而lambda表达式本身会创建匿名类型的新实例。根据lambda“

当在热代码路径中使用时,返回专用可选类型的调用函数是否会以增加GC压力为代价,而不是返回一个原语值来表示不存在(
Integer.MIN_value

编辑

我之所以不认为它们会像任何其他类一样执行堆分配,是因为
Optional
等是“”,这似乎意味着它们在幕后的行为可能与传统类不同。

是的

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

此外,这些类型鼓励使用lambda表达式,而lambda表达式本身会创建匿名类型的新实例。根据lambda“close-over”的值,您可能最终会看到这些对象也引用了其他对象,这会对GC产生一些影响

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

更新 Java8引入了基于值的类的概念,作为Java10“值类型”的一个有希望的垫脚石

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

Goetz:对于将Java8引用类型迁移到Java10值类型的想法,人们可能有点乐观。基本上,我们已经打下了基础,指出开发人员不能依赖某些属性(如身份检查),这些属性对于将来可能成为值类型的类型来说必然是真的。这种迁移在实践中是否可行还有待观察

因此,在Java8中,这些类仍然像普通类一样工作,但是通过对它们进行某些限制,有希望在Java10获得该功能时将它们转换为值类型

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

  • 提高了性能,因为您不需要使用堆空间
  • 值类型从不为null,因此,如果您有OptionalDouble类型的字段,并且从未对其进行初始化,则仍然不会得到null指针异常
  • 无耻的插件:我在C#中为我编写的库中的类型利用了结构类型的这些属性

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

    视情况而定™. 通常,
    可选的
    类型只是常规对象,因此是堆分配的。但在特定情况下,JIT编译器可能会将它们分解为字段(即它们所持有的值),并将它们放在堆栈上

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

    在标记后面似乎还隐藏着额外的实验性优化(
    -XX:+AggressiveUnboxing
    ,部分
    -XX:+AggressiveOpts
    )。据我所知,他们可能会破坏
    Integer.valueOf(int)
    的身份保证,因此不完全符合规范

    一个切线:实验/研究甚至更进一步,它可以将分配推迟到那些对象确实逃逸的代码路径,而当它们没有逃逸时,却将它们留在堆栈上进行标量分解。这还不是常规vm的一部分,主要由JRuby和Nashorn等JVM上运行的非java语言使用

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

    我之所以不认为它们会像其他类一样执行堆分配,是因为可选类等都是“基于值的类”

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

    我怀疑规范语言主要是为了在它们最终作为Java的一部分进入Java时提供对它们的前向兼容性


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

    它们是对象,行为与任何其他对象一样。这取决于您在做什么。为什么不在有和没有可选的测试用例的情况下对用例进行基准测试?我很确定这不会成为你代码的瓶颈…请看我的编辑。可选类型是基于值的类,这似乎意味着它们的分配方式不同,或者可以利用某些优化。@w.brian:感谢您对此进行扩展。查看我的更新。