system.arraycopy高效源于绕过java执行路径直通内存,入口一次性校验后调用底层memcpy/memmove等cpu指令,jit内联为机器码,避开栈帧、gc屏障与解释器开销,但要求参数严格合规。

System.arraycopy 的高效性,不来自“写了更快的 Java 代码”,而在于它根本没走 Java 执行路径——它是一条直通内存的专用通道。
绕过 Java 运行时的重复开销
手动 for 循环每次读写数组都要执行完整校验:检查索引是否越界、元素是否为 null(引用类型)、目标数组能否接受该类型。这些操作在字节码层面对应反复的 aaload 和 aastore 指令,每次迭代都触发一次。
System.arraycopy 把所有合法性检查压缩到调用入口处一次性完成:源/目标非空、起始位置合法、长度非负、srcPos + length ≤ src.length、destPos + length ≤ dest.length、类型兼容——全通过后,直接跳入本地内存搬运逻辑,中间不再做任何 Java 层判断。
底层调用的是 CPU 级内存指令
它不是“用 C 写了个循环”,而是映射到高度优化的底层函数:
- 对齐且无重叠时,通常调用
memcpy,可被编译器展开为rep movsq(x86-64)或向量化指令(AVX/SVE) - 可能重叠时(如同一数组内移动),自动切换为
memmove语义,按方向选择正序或倒序搬运,避免数据覆盖 - JIT 编译器(如 HotSpot C2)会将其识别为 intrinsic 方法,在热点代码中直接内联为机器码,甚至插入预取(prefetch)指令提升缓存效率
不触发额外 JVM 机制干扰
它避开多个性能敏感环节:
- 无方法调用栈帧开销:不创建新栈帧、不压参、不跳转返回
- 不触发 GC write barrier(尤其在年轻代内拷贝对象数组时)
- 不经过解释器,不依赖字节码解释路径;即使禁用 JIT,也仍走本地实现,而非退化为慢速循环
- 对基本类型数组,是纯位拷贝;对引用类型数组,只复制引用值,不递归处理对象内容
高效有前提:参数必须精准合规
它的快,是以严格约束为代价的:
- 目标数组必须已分配且长度足够,arraycopy 不负责扩容
- 源与目标数组组件类型必须兼容:int[] ↔ int[] 可,int[] → long[] 不可,String[] → Object[] 可,Object[] → String[] 不可
- 小数组(≤16 元素)可能因 JNI 调用开销反而不如简单赋值,需结合场景判断
- 所有越界或类型错误都在运行时立即抛异常,不静默容错











