应优先使用 system.arraycopy 或 arrays.copyof,因其绕过 java 层循环开销,经 jit 专项优化并支持 simd,而手动循环因频繁边界检查、解释执行及缓存不友好导致性能显著下降。

手动编写循环拷贝数组看似直观可控,但实际在 Java 中属于低效且易出错的写法,核心问题不在“能不能写”,而在于它绕不开 JVM 的运行时开销和优化限制。
每次循环都要重复做一堆检查
Java 字节码里,每个 aaload(读)和 aastore(写)操作都必须独立校验:
- 源数组长度是否越界(每次读前都要查一次
src.length) - 目标数组长度是否够用(每次写前再查一次
dest.length) - 如果是引用类型数组,还要做 null 检查和运行时类型兼容性验证(比如把
Object[]往String[]里拷会直接抛异常) - JVM 解释执行循环结构:跳转、栈帧维护、条件判断,全都在 Java 层完成
JIT 编译器很难帮上忙
HotSpot 对普通 for 循环的优化很保守:
- 无法确定你写的循环语义是否安全——它不敢轻易向量化、也不敢保证无副作用
- 几乎不会内联成紧凑汇编,更不会启用 SIMD 指令(如一次搬 16 字节)
- 缓存行为差:每次读+写是两个离散内存访问,容易反复加载/驱逐 cache line
System.arraycopy 是 JVM 内建的“特权操作”
它不是靠“写了 C 代码”快,而是彻底跳过 Java 层约束:
- 参数一次性校验(源/目标非空、索引合法、长度非负、类型兼容),之后直接调用类似
memmove的底层函数 - JIT 对它专项优化:自动内联、识别连续内存后启用 SIMD、配合 GC 卡表减少写屏障
- 对
byte[]等基础类型,带宽可逼近硬件 memcpy 极限
小数组不明显,大数组差距拉满
性能差异不是线性的,取决于数组长度:
- 长度 拷贝收益)
- 长度 20–1000:arraycopy 开始稳定胜出,优势随长度加速扩大
- 长度 > 10⁵:实测差距可达 3–5 倍,在高吞吐服务中直接影响 QPS
日常开发推荐用 Arrays.copyOf——它是 System.arraycopy 的安全封装,自带扩容逻辑,语义清晰,也避免裸调 native 方法的边界风险。











