system.arraycopy是jvm原语级内存搬运指令,参数协同控制物理读写路径:destpos>srcpos时自动倒序防覆盖,destpos<srcpos时正向执行,length=0可零成本校验边界与类型。

System.arraycopy 不是普通工具方法,它是 JVM 内部直接调度内存搬运指令的“原语级”操作。用好它,关键不在记住语法,而在于理解五个参数如何协同控制物理内存的读写路径。参数填对了,它自动走 SIMD 或 memmove;填错一点,还没开始搬数据,就抛异常中断。
同一数组内重叠拷贝:方向由 srcPos 和 destPos 的大小关系隐式决定
当 src 和 dest 是同一个数组时,arraycopy 会根据 destPos 是否大于 srcPos,自动选择正向或反向执行顺序,避免覆盖——这是它区别于 memcpy、接近 memmove 的核心能力:
- destPos > srcPos(向右移):JVM 自动从高下标往低下标复制,例如 System.arraycopy(arr, 2, arr, 5, 4) 安全地将 arr[2]–arr[5] 搬到 arr[5]–arr[8],等价于倒序循环
- destPos System.arraycopy(arr, 4, arr, 1, 4) 把 arr[4]–arr[7] 填入 arr[1]–arr[4],不会误读已被覆盖的 arr[4]
- destPos == srcPos:等同于空操作(若 length > 0),实际不搬运,但完成全部边界与类型校验
length = 0 是合法且有价值的“零成本校验”手段
传入 length 为 0 不会触发任何内存搬运,但 JVM 仍会完整执行所有运行时检查:
- 验证 src 和 dest 非 null
- 确认 srcPos ≥ 0 且 srcPos ≤ src.length
- 确认 destPos ≥ 0 且 destPos ≤ dest.length
- 检查类型兼容性(如 String[] → Object[] 合法,反之抛 ArrayStoreException)
适合在正式拷贝前做轻量预检,比如封装工具方法时先调用一次 System.arraycopy(src, srcPos, dest, destPos, 0),捕获异常再报业务错误,避免后续逻辑被越界打断。
跨数组拷贝时,用数学关系替代“直觉估算”防越界
越界不是靠经验判断,而是两个硬约束必须同时成立:
- srcPos + length ≤ src.length(不能写成 length ≤ src.length − srcPos,因为减法可能溢出)
- destPos + length ≤ dest.length
推荐在关键路径使用 Math.addExact 进行安全加法校验,或直接写为:
if (length > src.length - srcPos || length > dest.length - destPos) throw new IllegalArgumentException(...);基本类型数组迁移:让 JIT 真正启用向量化搬运的关键条件
int[]、byte[]、long[] 等基本类型数组的拷贝速度差异极大,取决于是否满足 JIT 内联为硬件指令的条件:
- 源和目标地址需自然对齐(如 16 字节对齐),JIT 才可能选用 AVX-512 或 SVE 向量指令
- length 最好是常量或编译期可推导值(如 1024、4096),利于循环展开
- 避免在循环体内反复调用 arraycopy 处理极小块(如每次 length=1~4),JNI 开销可能反超简单赋值
- 不要混用不同基本类型数组——int[] 拷到 long[] 编译不报错,但运行必抛 ArrayStoreException,且无隐式转换











