system.arraycopy快是因为它绕过java执行流程:一次性参数校验后,由jvm直接调用底层memmove/memcpy等指令完成内存块搬运,跳过字节码循环、重复边界检查与jit编译开销。

System.arraycopy 不是普通 Java 方法,它是 JVM 直接调度底层内存指令的“快捷通道”。它快,不是因为写得巧,而是因为它根本没走 Java 执行流程——参数校验一次完成,随后交由 C/C++ 实现的 memmove 或 memcpy 完成字节级搬运。
native 背后的真实执行路径
你写的那一行 arraycopy 调用,实际触发的是 JVM 内部一条高度特化的调用链:
- JVM 查找注册的 JNI 函数入口
JVM_ArrayCopy(位于 HotSpot 的jvm.cpp) - 根据数组类型(
int[]还是Object[])、是否重叠、是否同类型,分发到typeArrayOopDesc::copy_array或objArrayOopDesc::copy_array - 最终跳转至平台专属汇编 stub(如
copy_memory),调用memcpy(无重叠)或memmove(支持重叠) - 整个过程绕过解释器、不触发 JIT 编译决策、不插入 GC 写屏障,也没有对象包装开销
为什么必须是 native:Java 层无法绕过的三道坎
Java 数组访问(如 a[i])每次都要做三件事:空指针检查、索引越界检查、类型兼容性验证。这些在循环里重复发生,JIT 也难以完全消除。而 arraycopy 把全部检查集中到入口一次性做完,之后就“放手”:
- 校验项包括:源/目标非空、起始位置 ≥ 0、长度 ≥ 0、
srcPos + length ≤ src.length、destPos + length ≤ dest.length、组件类型可赋值 - 校验通过后,JVM 进入受信任上下文,直接调用 CPU 块复制指令(x86 的
rep movsb,ARM 的ldp/stp) - 这种“一次校验、批量搬运”的模式,正是 native 语义的核心价值
实战中必须守住的四条红线
arraycopy 高效但零容错,任何参数违规都会立即抛异常,没有“尽力而为”:
-
空数组:src 或 dest 为 null →
NullPointerException -
越界:srcPos、destPos、length 任一为负;或
srcPos + length > src.length;或destPos + length > dest.length→ArrayIndexOutOfBoundsException -
类型不兼容:运行时检查组件类型,
String[] → Integer[]失败,String[] → Object[]成功 →ArrayStoreException -
重叠逻辑依赖方向:同一数组拷贝时,JVM 自动选前向/后向策略(等价 memmove),但你要算准坐标——比如左移一位:
arraycopy(arr, 1, arr, 0, arr.length - 1),写反了就会丢数据
什么时候该用,什么时候绕开
它适合明确知道源/目标已存在、需精确控制起始与长度、追求极致性能的场景:
- 环形缓冲区消费后平移、网络包 payload 提取、日志批量刷盘
- 避免频繁 new 数组带来的 GC 压力(尤其在低延迟系统中)
- 需要重叠拷贝(如数组内移动)且不想手写循环+边界防护
- 不适合小数组(Arrays.copyOf 更安全简洁
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











