system.arraycopy 是 jvm 层级内存搬运指令,依赖参数精准控制,五类错误均抛明确异常且无静默降级;同数组拷贝时自动选向避免覆盖,但需严格满足边界条件;推荐前置校验、复用目标数组以提升稳定性。

System.arraycopy 不是普通复制工具,而是 JVM 层级的内存搬运指令。它不靠逻辑判断保安全,而靠参数精准控制物理搬运路径——用对了,系统更稳;错一个,立刻崩溃,不给机会。真正提升可靠性,靠的是参数校验前置、边界意识内化、以及对重叠拷贝行为的明确预期。
参数必须一次写对,不能靠“试运行”补救
五个参数中任意一个越界或类型不兼容,都会在运行时抛出明确异常,且无静默降级机制:
- src 或 dest 为 null → 立即抛 NullPointerException,不是空指针后继续执行
- srcPos、destPos 或 length 为负 → 抛 NegativeArraySizeException 或 IndexOutOfBoundsException
- srcPos + length > src.length 或 destPos + length > dest.length → 抛 ArrayIndexOutOfBoundsException
- int[] 往 long[] 拷、String[] 往 Integer[] 拷 → 运行时 ArrayStoreException,编译期不报错
同数组移位:JVM 自动选方向,但前提是你传对参数
当 src == dest 时,arraycopy 不是“复制”,而是内存重排。JVM 根据 srcPos 和 destPos 的大小关系自动决定正向或倒序执行,避免覆盖——但这不是容错机制,而是严格依赖你给出的安全区间:
- 左移(destPos :如 System.arraycopy(arr, 4, arr, 2, 5),JVM 正向搬运,安全
- 右移(destPos > srcPos):如 System.arraycopy(arr, 2, arr, 5, 5),JVM 倒序搬运,先搬高位再覆盖低位
- 禁止 srcPos == destPos 且 length > 0:虽合法,但浪费一次完整校验开销,属无效操作
- 必须满足 srcPos + length ≤ arr.length 且 destPos + length ≤ arr.length:这是 JVM 判定是否可安全执行的硬门槛
截取与拼接:边界预检比异常捕获更可靠
高频调用场景下,靠 try-catch 捕获 ArrayIndexOutOfBoundsException 是被动防御;提前校验才是主动加固:
- 截取前计算 len = to - from,检查 from ≥ 0、to ≤ src.length、from ≤ to
- 拼接前确保目标数组长度 = a.length + b.length,第二段 destPos 必须等于 a.length
- length = 0 是合法空操作,可用于快速预检边界:“System.arraycopy(src, from, dummy, 0, 0)” 可验证 from 是否越界
- 网络解析、日志切片等外部输入驱动的场景,务必在调用前做断言或 if-return,不把校验甩给 arraycopy
复用目标数组:零分配降低 GC 波动,提升服务稳定性
频繁 new 数组会触发 Minor GC,尤其在高吞吐服务中易造成 STW 波动。arraycopy 的核心优势之一,就是支持已有缓冲区复用:
- 预分配 byte[] pool,按 slot 划分,用 arraycopy 写入指定 offset,避免每次申请新 buffer
- 协议解析中,从大 buffer 截取 payload 时,只用 arraycopy 搬到业务小数组,而非整个复制
- 滚动日志或 RingBuffer 场景,靠两次 arraycopy 完成跨尾-头拼接,比手写循环更易被 JIT 优化,也更少出错
- 注意:dest 必须已初始化且类型匹配,不能指望 arraycopy 替你 new
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











