Value Classes 仍需要编译器同情
Value Classes Still Need Compiler Sympathy
JEP 401 作为 Valhalla 项目的里程碑,已在 JDK 28 中以预览功能形式集成。虽然 Value Classes 能显著提升语义表达能力并优化 JVM 性能,但盲目地将所有类都改为 Value Classes 并非良策。文章通过三个实例深入剖析:不可变性如何促成扁平化存储、去除身份标识如何消除分配开销,以及类型擦除在泛型虚拟调用中如何导致性能回退。作者强调,Value Classes 并非魔法,JVM 在不同场景下可能需要在扁平化表示和引用表示之间进行转换,理解这些底层机制对于编写高效代码至关重要。
我希望 Value Classes 不仅仅是魔法,今天我将展示 JVM 目前的能力及其局限性。
HN 评论区
45- DarkNova6
技术概述很棒,我完全同意结尾处的观点:
```
声明一个值类,首要的是一种语义上的决定。它告诉我们的同行程序员:其实例完全由其状态定义,不需要身份(identity)。这种更清晰的模型本身就有价值!JVM 额外拥有的优化这些值表示方式的自由,是一个令人欢迎的额外红利。
```
许多开发者似乎认为“用了值类,性能就起飞”,但事实要微妙得多。我们不应该只想着“但是性能呢”,而应该思考底层数据的本质。至少,这直接将一些核心的领域驱动设计(DDD)理念融入了语言之中。正因如此,我很高兴 `tearing` 默认没有开启。
Java 一直是一门致力于让库易于使用的语言,它非常信任库的作者并强调强封装。现在,专家可以从 JVM 中获得显著更多的性能,而水平稍逊的程序员则能避免制造出他们意想不到的 bug。
- pfdietz
Common Lisp 有一些值类型,具体来说是数字和字符。任何实现都可以在任何时候复制这些对象。因此,不应在数字或字符上使用 EQ 函数,因为结果可能不可预测。通常应该使用比较函数 EQL 来代替。
(整数和字符也通常由“即时”值表示,这些值 resides 在原本是指针的地方;对于这些类型,EQL 和 EQ 总是做同样的事。但分配在堆上的大整数和更大的浮点数则可能不同。)
将 Common Lisp 扩展为拥有类似操作的类型会很有趣。例如,那些不通过对象身份比较,而是通过其字段的 EQL 进行比较的结构。我推测这里讨论的 Java 值类型就是这类。
值类型的一个优点是它们与分布式计算配合得很好。序列化/反序列化后,值保持不变;不需要引用位于另一台计算机上的对象。
- aatd86
当然需要,无论是什么语言。这就是为什么我们有像字符串驻留(string interning)这样的东西。:)
- pan_lid
JVM 的逃逸分析(escape analysis)向来是时灵时不灵。很高兴看到它变得更有可预测性了。
- ferrule
这里主要是逃逸分析在干重活。在它完全可靠之前,你仍然是在猜测分配情况。