system.arraycopy 是 jvm 提供的内存块搬运指令,不创建对象、不触发 gc、不逐元素校验,仅做一次参数检查后调用底层 c 函数(如 memmove)实现高效平移。

System.arraycopy 不是“复制函数”,而是 JVM 提供的内存块搬运指令。它不创建新对象、不触发 GC、不逐元素校验,只做一次参数合法性检查,随后直接调用底层 C 函数(如 memmove 或 memcpy)完成整块内存平移——这才是它快的本质。
它绕开了 Java 层所有重复开销
手动 for 循环每次读写都要执行:
- 索引边界检查(是否
- 空指针与类型兼容性验证(尤其对象数组)
- 字节码解释或 JIT 编译循环结构本身带来的跳转、寄存器保存等开销
而 System.arraycopy 把全部校验压缩到入口处:src 和 dest 非 null、srcPos/destPos ≥ 0、length ≥ 0、srcPos + length ≤ src.length、destPos + length ≤ dest.length、运行时类型兼容——全通过后,直接进入裸地址搬运。
底层真正干了什么?
在 HotSpot JVM 中,调用链路是:
- Java 层调用 System.arraycopy(...) →
- JVM 跳转到 native 入口 JVM_ArrayCopy →
- 根据数组类型(基本型 / 对象型)、是否同数组、是否重叠,选择 copy_array 子路径 →
- 最终调用平台相关汇编 stub(如 copy_memory),使用 rep movsq(x86)、ldp/stp(AArch64)或 AVX-512 向量指令批量搬移
若源目标为同一数组且区间重叠(如左移清理头),JVM 自动选用后向拷贝(类似 memmove),避免数据覆盖;手动 memcpy 则无法保证这点。
为什么它接近“零拷贝语义”?
它不是真正的零拷贝(不绕过 JVM 堆),但在堆内做到了最简路径:
- 不新建对象,不产生中间引用,不触发 write barrier(年轻代内搬运时)
- 无 Java 方法调用栈帧开销,无参数压栈/返回跳转
- 支持 CPU 硬件预取(prefetch)、自然对齐优化、SIMD 并行搬运
对 512MB 的 byte[],主流服务器上通常耗时 5–10ms;而同等 for 循环可能需上百毫秒,且随数组增长线性恶化。
实战中必须守住的底线
高效的前提是参数绝对合法,任何错误都会立即抛异常,没有容错:
- src 或 dest 为 null → NullPointerException
- srcPos、destPos 或 length 为负 → NegativeArraySizeException 或 IndexOutOfBoundsException
- 越界(如 srcPos + length > src.length)→ ArrayIndexOutOfBoundsException
- 类型不兼容(如 int[] 拷到 long[],或 String[] 拷到 Integer[])→ ArrayStoreException
注意:编译期不报错,运行时才校验元素类型;Object[] 拷到 String[] 可能成功,但遇到非 String 元素时当场失败。











