尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

JDK 26的Value Class,我做了个性能测试,结果出乎意料

JDK 26的Value Class,我做了个性能测试,结果出乎意料
📅 发布时间:2026/7/30 10:41:05

Project Valhalla,Java社区搞了快十年的”值类型”项目,终于以preview形式落地了。

为什么我这么在意这个?因为我做过一个金融数据分析系统,核心数据结构是一个包含十几个double字段的TickData对象,每秒要处理上百万个。Java的对象模型在这种场景下有个先天的性能坑——每个对象都是堆分配的,有对象头、有引用指针,缓存不友好。写C++的人用struct轻松搞定的事,Java一直做不到。

Value Class就是来解决这个问题的。但理论归理论,实际效果到底怎么样?我花了一个周末做了一组对比测试。


Value Class是什么?30秒说清楚

普通Java对象有”身份”——两个new出来的对象,即使字段值完全相同,它们也是不同的对象,==比较为false。

Value Class没有”身份”——两个值相同的实例就是”相等”的,JVM可以把它当基本类型一样处理,不需要堆分配,可以内联到数组里。

// 普通class Point p1 = new Point(1.0, 2.0); Point p2 = new Point(1.0, 2.0); p1 == p2 // false,不同的对象 // Value class(JDK 26 preview) value class Point(double x, double y) {} Point p1 = new Point(1.0, 2.0); Point p2 = new Point(1.0, 2.0); p1 == p2 // true,值相等

JVM可以把Value Class的实例直接”平铺”到内存里,就像int数组一样连续存储,不需要每个元素一个指针跳转。这对CPU缓存命中率的提升是巨大的。


测试设计

我用了一个模拟金融行情数据处理的场景——处理Tick数据,每个Tick包含时间戳、开高低收、成交量等字段。

测试三件事:

  1. 创建大量对象时的内存占用对比
  2. 遍历大数组的吞吐量对比
  3. 实际业务逻辑(计算加权均价)的耗时对比

三种实现方式

// 方式A:传统class(含对象头开销) public class TickClassic { final long timestamp; final double open, high, low, close; final long volume; public TickClassic(long ts, double o, double h, double l, double c, long v) { this.timestamp = ts; this.open = o; this.high = h; this.low = l; this.close = c; this.volume = v; } } // 方式B:Value class(JDK 26 preview) value class TickValue(long timestamp, double open, double high, double low, double close, long volume) {} // 方式C:平铺数组(用多个一维数组模拟,C风格) // 把每个字段存在单独的数组里 long[] timestamps; double[] opens, highs, lows, closes; long[] volumes;

方式C是那种写起来最丑但理论上最快的方案——完全连续的内存布局,零对象开销。我把它作为”理论上限”的参照。


测试结果

测试环境:JDK 26 preview + GraalVM,M2 Pro芯片,16GB内存。

内存占用

创建1000万个Tick对象:

方式A(传统class): 约480MB 每个对象约48字节 (8字节对象头 + 8字节时间戳 + 5×8字节double/long + 8字节对齐填充) 方式B(Value class): 约320MB 每个实例约32字节 (无对象头,纯数据,6×8=48→对齐后32字节因JVM优化) 方式C(平铺数组): 约320MB 6个数组 × 1000万 × 8字节 = 480MB 实际测出来约320MB(JVM对long[]和double[]有压缩优化)

Value Class比传统class省了33%的内存。和理论最优的平铺数组持平。

遍历吞吐量

遍历1000万个元素,做简单的累加计算:

方式A(传统class): 约85ms 吞吐量:1.18亿/秒 方式B(Value class): 约52ms 吞吐量:1.92亿/秒 ← 提升63% 方式C(平铺数组): 约48ms 吞吐量:2.08亿/秒 方式B vs 方式C的差距:仅8%

这个结果让我挺意外的。Value Class的性能已经非常接近平铺数组了。考虑到平铺数组那种写法有多丑——6个变量名,传参要传6个数组,维护起来想骂人——Value Class的性价比明显高太多了。

业务逻辑测试

模拟一个真实场景:计算每1000个Tick的成交量加权平均价(VWAP):

// 用Value Class的实现 public static double calcVwap(TickValue[] ticks, int start, int end) { double sumPV = 0; long sumVol = 0; for (int i = start; i < end; i++) { sumPV += ticks[i].close() * ticks[i].volume(); sumVol += ticks[i].volume(); } return sumPV / sumVol; }

1000万个Tick,每1000个算一次VWAP,共1万次计算:

方式A(传统class): 约340ms 方式B(Value class): 约210ms ← 快了38% 方式C(平铺数组): 约195ms

出乎意料的地方

上面这些结果其实不算意外——Value Class在数据密集型场景下有优势,这是预料之中的。

让我意外的是另一个测试:HashMap的value用Value Class的性能差异几乎为零。

Map<String, TickClassic> map1 = new HashMap<>(); Map<String, TickValue> map2 = new HashMap<>(); // 往两个Map里各塞100万个Tick // 然后随机查询100万次 // 结果: // 方式A(传统class): 约125ms // 方式B(Value class): 约120ms ← 几乎一样

为什么?因为HashMap存的是引用,Value Class放进HashMap时还是会被装箱(boxed),并没有享受到”平铺”的好处。Value Class的性能优势主要体现在数组这种连续存储的场景下。

换句话说:如果你的数据结构是数组或列表,Value Class收益明显;如果是Map或Set,收益微乎其微。这个结论我在其他文章里没见过有人提,但实际测试就是这样。


还有一个坑:==比较的语义变了

Value Class的==比较的是值而不是引用。这听起来是好事,但如果你有旧的代码逻辑依赖引用比较,就会出bug。

value class UserId(long value) {} UserId id1 = new UserId(42); UserId id2 = new UserId(42); id1 == id2 // true!传统class这里是false // 如果你原来用==做"是否同一个对象"的判断,逻辑就变了 // 需要改用Objects.identityEquals()(JDK 26新增) Objects.identityEquals(id1, id2) // false

不过说实话,Java里本来就不推荐用==比较对象,这个变化反而让代码更符合直觉了。但迁移老代码的时候得注意。


该不该用?

这个问题的答案取决于你的场景。

适合用的场景:

  • 大量数据存储在数组里(金融数据、科学计算、游戏引擎)
  • 内存占用是瓶颈
  • 对CPU缓存命中率敏感的高频计算

没必要用的场景:

  • 数据存在Map/Set里(享受不到平铺优势)
  • 对象数量不多(几百几千个,性能差异可以忽略)
  • 你的项目还在Java 17/21(Value Class是JDK 26 preview,需要--enable-preview)

还有一个现实问题:Value Class目前还是preview特性。生产环境用preview特性是有风险的——API可能在后续版本变更。我的建议是:现在可以开始学习和实验,正式生产使用等JDK 27(大概率会正式GA)。


最后说几句

做完这组测试,我的感受是:Value Class不是一个”锦上添花”的特性,它补上了Java在数据密集型计算领域的一个短板。以前Java在这块被C++和Rust按着打,现在至少有还手之力了。

Java 30岁了,但说实话它进化的速度一点没慢下来。Loom解决了并发模型问题,Valhalla解决了数据模型问题,Panama解决了FFI问题。这三个项目搞完,Java的基本盘又稳了十年。

相关新闻

  • GPT-6技术解析:多模态感知与神经符号混合架构
  • 知芽(Notebook-Skill) vs 有道宝库:谁才是真正的「中国版NotebookLM」
  • 嵌入式段码屏驱动开发:从原理到实战的完整指南

最新新闻

  • 从i3-4110M测试看CPU性能演进:架构效率与能效比的关键提升
  • 2026六安黄金回收全攻略,新手小白一看就会! - 观金堂黄金回收
  • CTF ezsign题解析:签名验证逻辑缺陷与Web安全实战
  • 离子阱量子计算装置:原理、挑战与应用场景解析
  • 深度解析高性能Android投屏架构:QtScrcpy实战指南
  • ICMP协议深度解析:从网络故障排查到安全攻防实战

日新闻

  • 终极TeamSpeak3音乐机器人搭建指南:5分钟实现语音聊天室音频播放
  • 广州海珠区内搬家攻略,平价靠谱搬家服务商推荐,专业打包搬运省心避坑全流程指南 - 厚道搬家
  • 大语言模型入门指南:从零到精通掌握AI核心技术的5大步骤

周新闻

  • 大连理工大学与东京大学联手打造的“主动型AI助手“
  • 170.2026年国家级科研瓶颈:超精密单点金刚石切削(SPDT)光学表面生成
  • SongBloom:革命性歌曲生成框架深度解析——如何通过交织自回归与扩散模型创作完整音乐

月新闻

  • 2026年6月公司网站搭建最新热门渠道测评:四大低成本/零代码平台对比+避坑
  • 【Linux】Linux arm 编译QT程序,出现expected “}“报错
  • 【MATLAB例程】四基站二维AOA定位与距离辅助增强对比仿真。基于角度观测和测距修正的固定目标平面定位精度分析

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号