system.arraycopy极速运行的关键是满足硬件与语义约束以触发jvm底层memmove或simd指令:目标数组必须预先存在且容量充足;源目标类型须字节级兼容(如int[]→int[]);索引参数必须严格合法;长度建议≥256、优先使用基本类型数组,并依srcpos与destpos大小关系确保原地移位方向正确。

要让 System.arraycopy 在内存层面真正跑出极速,关键不是“调用它”,而是让它在 JVM 底层直接触发 memmove 或 SIMD 指令——这只有在严格满足硬件与语义约束时才会发生。
必须提前配齐三样“硬件”
它不分配内存、不检查逻辑、不处理异常恢复,只搬数据。所以迁移前得手动备好:
-
目标数组已存在且容量刚够:比如要迁 128KB 的
byte[],目标数组长度至少为destPos + 131072(字节数 = 元素数)。少一个就抛ArrayIndexOutOfBoundsException,没有商量余地。 -
源和目标类型字节级对齐:
int[] → int[]、byte[] → byte[]最快;String[] → Object[]可行但慢一档;int[] → long[]直接报ArrayStoreException,JVM 不做任何转换。 -
所有索引参数运行前可判定安全:建议封装校验逻辑,例如:
if (srcPos src.length || destPos dest.length) throw new IllegalArgumentException();
大体积 ≠ 无脑用,要看数据流向
真正拉开速度差距的,是场景匹配度:
-
固定缓冲区复用:如网络收包后,把
packet[headerLen..end]整块搬进预分配的byte[65536]起始位置——避免每次 new 数组触发 GC。 -
环形缓冲区腾空间:读指针后移导致头部空闲?用
arraycopy(buffer, readPos, buffer, 0, unreadCount)一次性前移,JVM 自动按安全顺序执行,不怕重叠。 -
ArrayList 扩容迁移:内部
grow()就是new int[old.length * 2]+arraycopy,整块搬运比逐个 add 快 3 倍以上。
让 JVM 愿意给你开“高速通道”
小数据它懒得优化,大数据它才调用底层指令。实测有效策略:
-
长度尽量用常量:写
1024比写len更易被 JIT 内联;阈值建议设为 256 起启用,≤64 时 for 循环反而更稳。 -
基本类型优先:
byte[]、int[]走纯内存路径,无 GC write barrier;对象数组只拷引用,快但后续修改会联动。 -
避开多线程争抢:单次调用原子,但不线程安全;多个线程往同一
dest不同区域写,可能撕裂数据——应加锁,或改用“新数组 + 原子引用替换”。
原地移位时方向不能错
同一数组内搬数据,本质是覆盖。方向由 srcPos 和 destPos 大小关系决定,JVM 自动选序:
- 向右移(
destPos > srcPos):自动倒序搬,防止未读数据被提前覆盖。 - 向左移(
destPos ):自动正序搬,安全高效。 - 示例:把
arr[3..7]左移 2 位 →System.arraycopy(arr, 3, arr, 1, 5);若误写成destPos = 0且数组不够长,立刻越界。











