system.arraycopy 的高吞吐源于 jit 将其内联为硬件指令(如 rep movsq、ldp/stp、avx),而非 jni 本身;需满足参数稳定、类型明确、禁用解释执行等条件,并避免小数组滥用,方能触发优化。

System.arraycopy 本身不是“JNI方法”,而是 Java 标准库中一个被 JVM 特别标记为 intrinsic(内建固有函数) 的 native 方法。它底层通过 JNI 进入 JVM 内部,但真正带来吞吐收益的,不是 JNI 调用本身,而是 JVM(尤其是 HotSpot C2 编译器)在运行时将其直接替换为硬件级内存指令——比如 rep movsq(x86)、ldp/stp(AArch64)或 AVX/SVE 向量指令。所以,“用 JNI 方法提升吞吐”这个说法容易误导;正确做法是:让 arraycopy 稳定触发 JIT 的 intrinsic 优化路径。
以下四点,直击吞吐收益关键:
✅ 确保调用能被 JIT 内联为机器指令
JIT 只对满足严格条件的 arraycopy 调用启用 intrinsic 优化:
- 参数全部为编译期可推导的常量或稳定变量(如
length = 1024比length = n更易优化) - 源/目标数组类型明确且兼容(
int[] → int[]、String[] → Object[]),避免泛型擦除后桥接调用 - 不包装在泛型工具方法里(例如
public <t> void copy(T[] a, T[] b)</t>会破坏内联机会) - JVM 启用默认优化(
-XX:+UseIntrinsics默认开启;禁用-Xint或-XX:TieredStopAtLevel=1)
✅ 避免小数据量反向拖累
吞吐收益在中大数组(>64 元素)才显著:
- 长度 ≤ 16:JNI 入口开销 + 安全校验可能超过简单赋值,实测反而更慢
- 长度 1000+:
arraycopy吞吐通常是 for 循环的 3–5 倍(尤其byte[]/int[]) - 建议:对长度动态的场景,加阈值分支
if (length
✅ 利用重叠安全搬运减少中间拷贝
网络缓冲区、RingBuffer、数组左移/右移等场景,直接原地平移:
-
System.arraycopy(buf, 1, buf, 0, len - 1)→ 左移一位,JVM 自动后向拷贝,无撕裂 - 替代方案(先
Arrays.copyOfRange再写回)会多一次堆分配和 GC 压力,吞吐下降明显
✅ 控制内存布局以激活硬件加速
高性能吞吐依赖 CPU 缓存与向量化:
- 尽量让源/目标数组地址自然对齐(如 64 字节对齐),JIT 更可能启用 AVX-512 单次搬 64 字节
- 连续操作同类型基本数组(
byte[]处理协议包、float[]做信号处理)最受益 - 对象数组只复制引用,不触发 write barrier,老年代间拷贝也轻量
不复杂但容易忽略。











