system.arraycopy比for循环快得多,因其是jvm内置native方法,一次性校验后直接调用底层内存指令(如rep movsq、memmove)整块搬运,跳过字节码循环、逐元素边界检查及类型验证,小数组快2–5倍,大数组逼近memcpy极限。

System.arraycopy 是 Java 中真正“物理级”数组拷贝的唯一标准方式——它不创建新对象、不走字节码循环、不逐元素校验,而是由 JVM 直接调度 CPU 内存指令完成整块搬运。快不是偶然,是设计使然。
为什么它比 for 循环快得多
手动 for 循环每拷一个元素,都要执行一次 aaload 和 aastore 字节码:每次读前检查索引是否越界,写前再检查一次,还要做 null 判断和运行时类型验证。而 System.arraycopy 在入口处一次性做完全部合法性校验(null、长度、索引范围、类型兼容),之后直接调用底层内存函数(如 memmove),全程无分支、无跳转、无栈帧压入。
- 小数组(
- 中等数组(20–1000)性能稳定领先,差距随长度扩大
- 大数组(> 10⁵)实测吞吐可达 for 循环的 3–5 倍,逼近硬件 memcpy 极限
它到底在底层做了什么
HotSpot JVM 把 System.arraycopy 视为“语义原子操作”,JIT 编译器会将其编译成平台专属的高效机器码:
- x86-64 上常生成
rep movsq(一次搬 8 字节)或 AVX-512 指令(单次搬 64 字节) - AArch64 上倾向用
ldp/stp成对加载/存储,或 SVE 向量指令 - 自动按缓存行(64 字节)对齐搬运,插入预取指令,匹配 CPU 流式预取器
- 支持非临时存储(non-temporal store),绕过缓存直写内存,避免写分配开销
参数必须严格合法,但容错逻辑很聪明
五个参数缺一不可,顺序固定:System.arraycopy(src, srcPos, dest, destPos, length)。任何非法输入立刻抛异常,不沉默、不截断:
-
src或dest为 null →NullPointerException length → <code>NegativeArraySizeException-
srcPos + length > src.length或destPos + length > dest.length→ArrayIndexOutOfBoundsException - 源与目标类型不兼容(如
int[]往String[]拷)→ArrayStoreException - 当
src == dest且区间重叠时,JVM 自动选正向或反向搬运,语义安全(比如arraycopy(arr, 0, arr, 1, 5)不会覆盖未读数据)
它适合做什么,不适合做什么
System.arraycopy 只干一件事:把一块内存内容,按字节粒度,搬到另一块内存。因此:
- ✅ 适合:动态扩容(如 ArrayList 底层)、环形缓冲区滚动、header 截取、原地移位(删除后前移)、复用已有 buffer
- ✅ 适合:大数组、基本类型数组(
byte[]、int[])拷贝,性能收益最显著 - ❌ 不适合:替代
Arrays.copyOf()去“生成新数组”——它不分配内存,目标数组必须提前存在 - ❌ 不适合:需要深拷贝对象内部状态的场景——它永远只浅拷贝,引用数组搬的是地址,不是对象本身
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











