System.arraycopy高效需JIT跳过Java层生成硬件指令,要求预分配目标数组、长度充足、避免循环新建、大数组启用、length用编译期常量、基本类型优先、类型严格匹配、禁用泛型中转、不支持跨类型转换、支持原地重叠拷贝。

System.arraycopy 不是“写对就能快”的工具,而是需要配合 JVM 运行机制和内存布局才能释放全部性能的底层原语。它真正高效的前提,是让 JIT 编译器顺利跳过 Java 层逻辑,直接生成硬件级内存搬运指令。
确保目标数组已预分配且容量充足
arraycopy 从不扩容,也不检查是否够用——越界就抛异常,不会容忍半点误差。
- 目标数组必须提前创建,长度 ≥ destPos + length;少一个元素就会触发 ArrayIndexOutOfBoundsException
- 避免在循环中反复 new 数组:每次分配都触发 GC 压力,尤其老年代对象复制可能引发 Full GC
- 高频场景(如网络包解析、RingBuffer)建议复用缓冲池,用 arraycopy 覆盖旧数据而非新建
只在大数组上启用,小数据走分支判断
实测表明,拷贝长度 ≤ 16 时,JNI 调用开销常高于简单赋值;256 是更稳妥的阈值。
- length 尽量用编译期常量(如 1024),JIT 更易向量化或展开为 SIMD 指令
- 若 length 来自运行时(如 packet.length),建议加 if 分支:小包用 for,大包用 arraycopy
- 基本类型数组(byte[]、int[])收益最大;对象数组拷的是引用,快但属浅拷贝
严格匹配类型,避开泛型擦除陷阱
它不做类型转换,也不容许桥接逻辑干扰 JIT 内联。
- int[] 只能拷到 int[],String[] 可拷到 Object[],但 Object[] → String[] 运行时报 ArrayStoreException
- 避免用 Arrays.asList().toArray() 或泛型工具方法中转——擦除后破坏内联机会,降级为普通循环
- 跨基本类型(如 int[] → long[])完全不支持,需手动转换或 Stream,性能损失显著
利用原地重叠拷贝能力,替代手动拆分
当 src == dest 时,JVM 按 memmove 语义自动保序,无需你干预方向或拆段。
- 右移(destPos > srcPos):自动倒序搬运,防止中间值被覆盖
- 左移(destPos
- 典型应用:RingBuffer 数据前移、ArrayList 删除首元素、切片后覆盖原位
多线程写同一 dest 数组必须隔离
单次调用原子,但不保证线程安全——CPU 缓存未同步会导致数据撕裂。
- 多个线程往同一数组不同区域写(如 [0,999] 和 [1000,1999]),仍可能因缓存不一致出错
- 推荐做法:各线程操作独立 buffer,最后用一次 arraycopy 合并;或用新数组 + AtomicReference.lazySet 替换引用
- 绝对不要在无锁场景下并发调用 arraycopy 到同一个 dest


















