System.arraycopy 是 Java 中唯一绕过 Java 层循环和边界检查、直接调用 JVM 底层内存搬运指令的原语,其高性能源于一次参数校验后调用类似 memmove 的 C 函数整块平移,不创建对象、不触发 GC、不逐元素校验。

System.arraycopy 是 Java 中唯一能绕过 Java 层循环和边界检查、直接调用 JVM 底层内存搬运指令的原语。它不创建新对象、不触发 GC、不逐元素校验,只做一次参数合法性检查后,就调用类似 memmove 的底层 C 函数完成整块数据平移——这才是它真正快的核心原因。
什么时候用才真正更快
提速不是无条件的,关键看数据规模和使用方式:
- 基本类型数组(
int[]、byte[]等)拷贝长度 ≥ 256 时,JVM 可启用 SIMD 指令批量搬运,优势明显 - 对象数组(
String[]、MyBean[])也快,但只复制引用,不触发 GC 写屏障,适合高吞吐场景 - 长度 ≤ 16 的数组,
for循环反而更快——JNI 调用开销盖过了搬运收益 - 避免在循环体内频繁调用;参数尽量用编译期可判定的常量,利于 JIT 内联
原地重排:不用手写方向判断
同一数组内移动数据(如删除首元素后前移、RingBuffer 左移),不必自己写 if 分支判断方向:
- 左移(
destPos < srcPos):例如System.arraycopy(arr, 4, arr, 2, 5)→ JVM 正向执行,不会覆盖 - 右移(
destPos > srcPos):例如System.arraycopy(arr, 2, arr, 5, 5)→ JVM 自动倒序搬运,防止数据丢失 - 只要满足
srcPos + length ≤ arr.length且destPos + length ≤ arr.length,重叠区间就安全合法
复用缓冲区:降低 GC 压力的关键
真正体现高性能的地方,是“不 new”的时候:
立即学习“Java免费学习笔记(深入)”;
- 预分配一个大
byte[] pool,按 slot 划分(如每 slot 4KB),用arraycopy把网络包写入指定偏移 - 切片提取 payload:从
packet中取有效段(如索引 12 开始 1024 字节),直接写入已存在的payloadBuf - 滚动日志或音视频解码中,靠两次
arraycopy完成跨尾部+头部的“折断拼接”,比手写循环更安全且易被 JIT 优化
避坑要点:错一个参数就崩
它不宽容,所有校验都在运行时一次性做,出错立刻抛异常,不静默:
-
src或dest为null→NullPointerException -
srcPos、destPos或length为负 →NegativeArraySizeException或IndexOutOfBoundsException -
srcPos + length > src.length或destPos + length > dest.length→ArrayIndexOutOfBoundsException -
int[]拷到long[]、String[]拷到Integer[]→ArrayStoreException(运行时报,非编译期) -
length = 0合法,可用于边界预检,不耗性能
它不是万能复制工具,而是精准控制内存落点的底层指令。用对了,就是高性能数据处理的基石;用错了,连运行都过不去。



















