jmh比手写system.nanotime()更可靠,因其自动处理预热、分叉、统计校验,避免jit未优化、gc暂停、cpu波动等干扰,确保结果可复现;需控制数组长度、数据类型、jit状态等变量,并覆盖小/中/大三档规模及基本/引用类型进行对比。

直接用基准测试工具(如JMH)测,比手写System.nanoTime()更可靠。关键不是“谁快”,而是“在什么条件下快得明显”——数组长度、JIT预热、GC干扰、数据类型都会影响结果。
选对测试工具和方法
避免自己写循环+System.nanoTime()测多次取平均。这种写法容易受JIT未优化、GC暂停、CPU频率波动干扰,结果抖动大、不可复现。
- 用JMH(Java Microbenchmark Harness):它自动处理预热、分叉(fork)、统计校验,是Oracle官方推荐的微基准测试框架
- 禁用不必要的JVM参数干扰:比如关掉G1的自适应调优(
-XX:-UseAdaptiveSizePolicy),固定堆大小(-Xms2g -Xmx2g) - 每个方法单独跑一个
@Benchmark方法,不要混在同一方法里顺序执行
控制核心变量,让对比有意义
效率差异在不同规模下表现不同。不能只测一次100万元素就下结论。
- 至少覆盖三档长度:小(100)、中(10,000)、大(1,000,000)
- 分别测基本类型(
int[])和引用类型(String[]):前者拷贝的是值,后者拷贝的是引用,System.arraycopy优势更明显 - 区分“首次执行”和“稳定态”:JMH默认5轮预热(warmup)+5轮测量(measuring),确保JIT已内联并优化
重点关注四种主流方式的实际表现
实测典型场景(JDK 17,Linux x86_64,1M个int)下,吞吐量排序稳定为:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- System.arraycopy:最快。本地实现 + HotSpot intrinsic优化,接近内存块复制速度
- clone():次快。也是native方法,但需目标数组已存在(一维)或需逐层调用(二维)
-
Arrays.copyOf:第三。内部调用
System.arraycopy,但多一次新数组分配开销 - for循环:最慢(尤其大数据量)。纯Java解释/编译执行,边界检查、分支预测等带来额外成本
注意:Arrays.copyOfRange和Arrays.copyOf性能几乎一致,因底层完全复用System.arraycopy;而二维数组拷贝时,clone()需配合循环使用,此时System.arraycopy仍保持领先。
别忽略实际开发中的隐性成本
最快 ≠ 最合适。要结合语义和维护性判断:
- 需要扩容?用
Arrays.copyOf——语义清晰,一行搞定 - 已有目标数组且需部分拷贝?用
System.arraycopy——零分配、可控偏移 - 只是浅拷一份副本,不关心底层?
clone()最简洁,可读性强 - 逻辑复杂(如跳过null、转换类型)?只能手动循环——这时效率本就不是瓶颈
真正影响系统性能的,往往不是拷贝本身,而是拷贝引发的内存分配、GC压力或缓存失效。与其死磕微秒级差异,不如先确认这里是不是热点路径。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










