system.arraycopy 是需精准匹配 jvm 底层路径的内存搬运原语,仅在基本类型数组≥256、对象数组浅拷贝、预分配目标数组等条件下显著提速,小数组反慢,且要求类型严格、参数校验、线程隔离。

System.arraycopy 不是“写了就快”的万能函数,而是需要精准匹配 JVM 底层执行路径的内存搬运原语。它快,是因为跳过 Java 层循环和逐元素检查,直连 memcpy 或 SIMD 指令;但它也苛刻——参数错一个就崩,条件不满足反而比 for 循环还慢。
什么时候该用 arraycopy?看数据量和类型
真正提速只发生在合适条件下:
- 基本类型数组(int[]、byte[]、long[])拷贝长度 ≥ 256 时,JVM 更可能启用 SIMD 向量化指令,性能优势明显
- 对象数组(String[]、MyBean[])拷的是引用,不触发 GC 写屏障,适合高吞吐场景,但仍是浅拷贝
- 长度 ≤ 16 的数组,JNI 调用开销常高于简单 for 循环;≤ 4 元素时,手写赋值通常更快
- 若 length 来自运行时变量(如 packet.length),建议加 if 分支:小数据走 for,大数据走 arraycopy
目标数组必须预分配且容量刚够
arraycopy 从不 new 数组,也不扩容。它只搬运,越界即抛异常:
- dest 数组必须非 null,且 length ≥ destPos + length;少一个元素就会触发 ArrayIndexOutOfBoundsException
- 避免在循环中反复 new 目标数组——每次分配都增加 GC 压力,尤其老年代复制易引发 Full GC
- 高频场景(如网络解析、RingBuffer)推荐复用缓冲池:预分配大 byte[],用 arraycopy 写入指定 offset
- Arrays.copyOf() 内部先 new 再 arraycopy,多一次堆分配;已有目标数组时,直接调用 arraycopy 可省 30%~50% 时间
原地重排:不用判断方向,JVM 自动保序
当 src == dest 时,arraycopy 按 memmove 语义处理重叠区间,自动选择搬运方向:
- 左移(destPos :如 System.arraycopy(arr, 4, arr, 2, 5),JVM 正向执行,安全覆盖
- 右移(destPos > srcPos):如 System.arraycopy(arr, 2, arr, 5, 5),JVM 倒序搬运,防止中间值丢失
- 边界贴线合法:System.arraycopy(arr, 7, arr, 6, 3) 把 [7,8,9] 搬到 [6,7,8],destPos + length == 9,不越界
- 禁止 srcPos == destPos 且 length > 0——虽不报错,但纯属浪费校验开销
避坑要点:类型严格、参数校验、线程隔离
它不宽容,所有错误都在运行时一次性爆发:
- 类型必须兼容:int[] 只能拷 int[];String[] 可拷 Object[],但 Object[] → String[] 运行时报 ArrayStoreException
- 参数全需提前校验:src/dest 不能为 null;srcPos、destPos、length 不能为负;srcPos + length ≤ src.length;destPos + length ≤ dest.length
- 多线程写同一 dest 数组不安全:单次调用原子,但 CPU 缓存未同步会导致数据撕裂;应各线程操作独立 buffer,最后合并
- length 尽量用编译期常量(如 1024),利于 JIT 内联与向量化;避免泛型中转或 Arrays.asList().toArray(),擦除后破坏优化机会
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











