System.arraycopy在多数场景下比手动for循环更快,但性能优势取决于数组长度、元素类型等条件:小数组(≤4)循环更优,中等规模(20–1000)arraycopy稳定胜出,大数组(≥10⁵)差距达3–5倍。

System.arraycopy 在多数场景下比手动 for 循环更快,但这个“快”不是绝对的——它取决于数组长度、元素类型、是否重用、JIT 编译状态等实际条件。关键不在“是不是 native”,而在于它绕开了 Java 运行时每次访问都要做的重复检查。
小数组(≤ 4 元素):循环可能更轻量
此时 arraycopy 的 JNI 调用开销(参数校验、上下文切换、native 方法入口)会超过拷贝本身收益。JVM 甚至可能把极小循环优化成展开形式(unroll),而 arraycopy 还没真正开始搬数据。
- 适合直接赋值或展开写死,比如 int[] arr = {a, b, c};
- 若需动态索引或条件判断,循环仍是唯一选择;arraycopy 不支持过滤或转换
中等规模(20–1000 元素):arraycopy 稳定胜出
优势随长度增长加速明显。JIT 已能稳定内联 arraycopy,并启用 SIMD 指令(如一次搬运 16 字节)。而 for 循环仍要为每个元素执行两次边界检查、一次 null 检查(对象数组)、一次写屏障(GC 相关)。
- int[500] 拷贝实测:arraycopy 约 0.01 ms,for 循环约 0.04 ms
- String[500] 拷贝:arraycopy 约 0.02 ms,for 循环约 0.07 ms(引用类型额外开销放大)
- 避免在循环里反复调用 arraycopy 拷 1 个元素——JNI 开销被严重摊薄
大数组(≥ 10⁵ 元素):性能差距拉到 3–5 倍
底层接近 memcpy 极限带宽。JVM 将其识别为连续内存块搬运,配合页对齐、预取、卡表批量更新等机制,GC 压力也更低。
- int[1_000_000] 拷贝:arraycopy 0.03–0.05 ms,for 循环 0.12–0.18 ms
- byte[] 或 char[] 等基础类型受益最大;对象数组虽受限于引用语义,仍有 1.5–2 倍提升
- 源与目标为同一数组时,arraycopy 自动按方向处理重叠(类似 memmove),无需手动分段
怎么用才不白费这波优化
写错参数或误用模式,反而让 arraycopy 变慢甚至抛异常:
- 目标数组必须预先创建且容量足够;否则抛 IndexOutOfBoundsException
- 类型兼容性只在入口校验一次:String[] → Object[] 合法,→ Integer[] 则 ArrayStoreException
- 别包装成泛型工具方法再调用——桥接方法破坏 JIT 内联,性能打七折
- 流式处理(如音视频帧、IoT 数据包)强烈推荐 arraycopy:低抖动、零新对象、GC 友好


















