system.arraycopy 在不同 jvm 版本间核心语义一致,但底层实现持续演进:jdk 9 起启用 intrinsic 内联与汇编优化,jdk 11+ 支持重叠检测与后向拷贝,gc 协同(g1/zgc/shenandoah)提升吞吐,小数组在 jdk 17+ 可被完全消除。

System.arraycopy 在不同 JVM 版本间的核心语义和行为保持一致,但底层实现细节、优化策略和适用边界随 HotSpot 演进而持续演进。它不是“固定不变的 native 函数”,而是 JVM 内核级的可调优原语,其实际执行路径高度依赖版本、平台、数组类型与大小。
JIT 内联与汇编生成策略升级
早期 JDK(如 JDK 7–8)中,System.arraycopy 多数场景会真实进入 JNI 层,调用 C++ 实现的 copy_array 函数;而从 JDK 9 开始,HotSpot 引入更激进的 intrinsic 内联优化:当方法被频繁调用且参数稳定时,JIT 编译器直接将其替换为紧凑汇编指令序列(如 x86 上的 rep movsb 或 AVX2 向量化搬移),完全绕过函数调用开销。JDK 17+ 进一步支持根据 CPU 特性自动选择 SIMD 指令宽度(128/256/512-bit),小数组甚至可能被展开为独立 mov 指令。
对重叠拷贝的处理更健壮
旧版 JVM(JDK 8 及之前)在源目标为同一数组且区间重叠时,仅靠简单前向拷贝,存在覆盖风险;JDK 9 起,HotSpot 增加了运行时重叠检测逻辑,并自动切换为后向拷贝(memmove 语义),保证语义正确性。例如 System.arraycopy(arr, 1, arr, 0, 4) 在 JDK 11+ 中能安全产出 [arr[1], arr[2], arr[3], arr[4]],而老版本可能得到错误结果。
GC 协同机制持续改进
不同 GC 算法对 arraycopy 的适配深度不同: • G1(JDK 9+):支持并发卡表(card table)批量标记,减少写屏障触发次数; • ZGC(JDK 11+):引入“无暂停复制”路径,在多数情况下避免阻塞式内存搬运; • Shenandoah(JDK 12+):允许跨代拷贝时跳过部分引用更新,降低 STW 时间。 这些优化不改变接口,但显著提升大对象数组在低延迟 GC 下的实际吞吐。
小数组处理策略差异化明显
对长度 ≤ 4 的拷贝,JVM 版本差异尤为突出: • JDK 8:仍走完整 native 调用,JNI 开销占比高,有时慢于手写赋值; • JDK 11+:启用 arraycopy intrinsic 的“微内联”模式,将拷贝展开为 2–4 条寄存器 mov 指令,性能反超循环; • JDK 17+:结合逃逸分析,若目标数组栈上分配,整个拷贝可能被完全消除(dead store elimination)。
不复杂但容易忽略:你写的 System.arraycopy 调用,在 JDK 8 和 JDK 21 中,底层可能分别是“一次函数跳转”和“零开销寄存器搬运”。选版本不如看实测——尤其在高频小拷贝或 GC 敏感场景,建议用 JMH + -XX:+PrintAssembly 验证真实行为。











