System.arraycopy高效复制大数组的关键在于JVM直接执行底层内存搬运,不走字节码循环、不分配新内存、只做地址平移;需确保目标数组容量充足、类型严格匹配、避免泛型擦除,小数组(≤16)反降效,256为推荐阈值,原地拷贝自动保序但不可替代逻辑校验,多线程写同一dest须加锁或原子引用替换。

System.arraycopy 高效复制大数组,核心不是“调用它”,而是让 JVM 顺利进入底层内存搬运路径——它不走 Java 字节码循环,不分配新内存,只做地址级平移。一旦参数失当或场景错配,性能优势立刻消失,甚至比 for 循环还慢。
目标数组必须提前配足容量,且类型严格匹配
它不做扩容、不转换类型、不兜底容错。复制前务必确保:
- dest 数组已存在,且 dest.length ≥ destPos + length;少一个元素就抛 ArrayIndexOutOfBoundsException
- src 和 dest 元素类型字节级兼容:int[] 只能拷到 int[],byte[] → byte[] 最快;String[] 可拷到 Object[],但反过来或跨基本类型(如 int[] → long[])会直接报 ArrayStoreException
- 避免泛型包装调用:用 Arrays.asList().toArray() 或泛型工具方法中转,会擦除类型、引入桥接逻辑,破坏 JIT 内联机会
大数组才值得启用,小数据反而拖后腿
实测表明,拷贝长度 ≤ 16 时,JNI 调用开销常高于简单赋值;256 是更稳妥的启用阈值:
- length 尽量用编译期可判定的常量(如 1024),JIT 更易向量化或展开为 SIMD 指令
- 若 length 是运行时变量(如 packet.length),建议加分支判断:小包走 for,大包走 arraycopy
- 基本类型数组(byte[]、int[])性能最优;对象数组拷的是引用,快但后续修改会影响源——这是浅拷贝本质,不是 bug
原地迁移要防覆盖,重叠区间由 JVM 自动保序
当 src == dest 时,属于原地移位(如删除元素后前移、环形缓冲区腾空),JVM 会根据 srcPos 与 destPos 的大小关系自动选择正向或反向拷贝,确保语义正确:
- destPos
- destPos > srcPos(右移):JVM 倒序执行,避免未读数据被覆盖
- 但 不能依赖“自动保序”来掩盖逻辑错误,比如 arraycopy(arr, 0, arr, 1, arr.length - 1) 看似合理,若 arr.length 为 0 或 1,仍会越界抛异常
多线程写同一 dest 数组须隔离
单次 arraycopy 调用是原子的,但方法本身不提供线程安全保证:
- 多个线程往同一 dest 数组的不同区域写入,可能因缓存行争用导致数据撕裂
- 应加锁,或改用“新数组 + 原子引用替换”策略(如用 AtomicReference 更新数组引用)
- 网络收包、环形缓冲区、ArrayList 扩容等典型场景,都是单线程主导的批量迁移,天然规避此问题

















