Java中toString性能测试必须用JMH工具,它能规避JVM预热、死码消除等干扰,提供稳定吞吐量或耗时数据;需引入jmh-core依赖,测试不同实现方式(+拼接、Objects.toString、StringBuilder、Lombok),并注意预热轮次、测量轮次、JVM参数及真实字段类型。

Java 中 toString 方法的性能测试不能靠猜,得用标准工具实测。最权威、最常用的是 JMH(Java Microbenchmark Harness),它能规避 JVM 预热、死码消除、常量折叠等干扰,给出稳定可信的吞吐量(ops/s)或平均耗时(ns/op)数据。
用 JMH 搭建 toString 基准测试
你需要在项目中引入 JMH 依赖(Maven):
<dependency> <groupId>org.openjdk.jmh</groupId> <artifactId>jmh-core</artifactId> <version>1.37</version> </dependency>
然后定义一个基准类,例如对含 3 个字段的 POJO 测试不同 toString 实现:
- 用 + 拼接(需手动 null 判断)
- 用 Objects.toString()(自动处理 null,可设默认值)
- 用 StringBuilder.append()(显式控制,适合复杂逻辑)
- 用 Lombok @ToString(编译期生成,实际等价于 StringBuilder 方式)
关键测试要点
真实反映性能差异,必须注意以下细节:
立即学习“Java免费学习笔记(深入)”;
- 预热轮次不少于 5 轮,每轮 1 秒,让 JIT 充分优化
- 测量轮次不少于 10 轮,避免单次抖动影响结果
-
禁用 GC 日志干扰,加 JVM 参数:
-XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly(可选) -
对象需脱离逃逸分析范围,用
@Fork(jvmArgs = {"-Xmx2g"})确保堆内分配 - 字段类型要贴近真实场景:String、int、List、嵌套对象,避免全 primitive 导致过度优化
典型测试结果解读
以含 name(String)、age(int)、tags(List<String>)的 User 类为例,JMH 输出类似:
Benchmark Mode Cnt Score Error Units ToStringBenchmark.plus avgt 10 142075167.0 ± 1234567.0 ops/s ToStringBenchmark.objects avgt 10 138922450.0 ± 987654.0 ops/s ToStringBenchmark.builder avgt 10 140333210.0 ± 1122334.0 ops/s
可见:字符串 + 拼接最快(JVM 自动优化为 StringBuilder),Objects.toString 略慢但更安全(多一次 null 判断和方法调用),StringBuilder 手写版居中且可控性最强。
避免常见误测陷阱
很多“性能对比”结果失真,往往因为:
- 没用 JMH,直接写 for 循环 + System.nanoTime() —— 受 JIT 编译阶段影响极大
- 测试对象是局部常量(如 new User("a", 1)),被 JVM 常量化或标量替换
- 未关闭日志框架的 toString 调用链(如 SLF4J 的参数延迟求值机制会掩盖真实开销)
- 忽略集合字段的 toString 递归开销(如 List.toString() 本身也走 StringBuilder)
真正有意义的测试,是把 toString 放进高频日志打印路径中模拟压测,比如每秒 10 万次 log.debug("user: {}", user)。



















