System.arraycopy 更快是因为绕过边界检查、避免字节码解释开销,并能被 JIT 深度优化(如自动向量化),而非仅因 native 实现;Java 数组访问每次隐式检查下标越界。

System.arraycopy 通常比手动循环拷贝快得多,尤其在数组较大或频繁调用时优势明显。 这不是因为“底层是 native”,而是因为它绕过了 Java 的边界检查、避免了字节码解释开销,并能被 JIT 编译器深度优化(如自动向量化)。但具体快多少,取决于数组类型、长度、JVM 版本和运行时环境。
为什么 System.arraycopy 更快
Java 数组访问每次都会隐式检查下标是否越界(a[i] 等价于 check(i )。手动循环中,每次赋值都要执行两次检查(源数组读 + 目标数组写);而 System.arraycopy 在 native 层一次性校验起始位置和长度,之后直接内存块搬运。现代 HotSpot JVM 还会对 arraycopy 做特殊内联与向量化处理,比如用 SIMD 指令一次拷贝 16 字节甚至更多。
典型性能差距(实测参考)
在 JDK 17 + Linux x86_64 上,对 int[] 拷贝 100 万个元素:
-
System.arraycopy:约 0.03–0.05 ms - 普通 for 循环(带局部变量缓存数组引用):约 0.12–0.18 ms
- 增强 for 循环(for-each):约 0.25–0.40 ms(因额外迭代器开销和边界检查更频繁)
差距随数组增大而拉大。对于 byte[],差异更显著——arraycopy 可接近 memcpy 速度,而循环受 JVM 对 byte 类型的特殊限制影响更大。
分析 Java Spring Boot 后端 Controller 代码,自动生成 Markdown 格式的接口文档。当用户说“生成 Java 接口文档”、“生成 API 文档”、“从 Spring 代码生成文档”时触发。
什么时候手动循环可能“不慢”
极小数组(如长度 ≤ 4)或需条件过滤/转换的场景,arraycopy 不适用,此时循环是唯一选择。另外,若循环体本身很重(如含复杂计算、方法调用),拷贝开销占比极小,优化意义不大。但只要目标是“纯复制”,就应优先用 arraycopy。
正确使用 System.arraycopy 的关键点
避免常见误用导致性能反降或异常:
- 确保源、目标数组类型兼容(如不能把
String[]拷到Object[]以外的数组) - 起始索引和长度必须合法,否则抛
ArrayStoreException或IndexOutOfBoundsException - 源与目标为同一数组时,支持重叠拷贝(类似 memmove),但方向要明确:
srcPos 时从后往前,反之从前往后 ——arraycopy自动处理,无需手动判断 - 不要为了“省代码”而在循环里反复调用
arraycopy拷少量元素(如每次拷 1 个),这会放大 JNI 调用开销
不复杂但容易忽略:多数情况下,直接用 System.arraycopy 就是对的。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










