System.arraycopy()不提供擦除语义,仅高效复制内存块;所谓“模拟缓存行擦除”是用0或null等默认值批量覆盖目标区域,实现逻辑重置,常用于环形缓冲区、滑动窗口等场景。

System.arraycopy() 本身不提供“擦除”语义,它只是高效复制内存块。所谓“模拟缓存行擦除”,实质是用指定值(如 0、null 或默认值)批量覆盖目标数组的一段区域,从而让旧数据在逻辑上失效——这在简易环形缓冲区、滑动窗口或对象池等轻量缓存场景中很常见。
明确目标:覆盖 ≠ 清零内存,而是重置逻辑状态
Java 中没有真正的内存擦除(不像 C 的 memset),但可通过覆盖实现等效效果:
- 基本类型数组(如 int[]):用 0、-1 或业务约定的“无效值”覆盖
- 引用类型数组(如 Object[]):用 null 覆盖,解除引用便于 GC
- 覆盖范围通常对应一个“缓存行”粒度(例如 16 个元素,对齐典型 CPU 缓存行大小)
用 arraycopy 实现“覆盖”的关键技巧
不能直接用 arraycopy(src, srcPos, dest, destPos, len) 把自己拷给自己来擦除——除非你构造一个全填默认值的临时源数组。更常用且高效的方式是:
-
准备一个静态默认值数组(复用避免频繁分配):
private static final int[] ZERO_LINE = new int[16]; // 全 0,JVM 会自动初始化 -
用 arraycopy 复制默认值到目标位置:
System.arraycopy(ZERO_LINE, 0, cacheArray, offset, lineLength); - 若需不同默认值(如 -1 表示“未命中”),可预先填充专用模板数组,或改用 Arrays.fill()(小范围更简洁,但底层非 memcpy)
环形缓冲区中擦除“最老一行”的典型用法
假设你维护一个固定大小的 byte[] buffer,按每 32 字节为一行管理,写满后从头覆盖:
- 计算待擦除行起始索引:int eraseStart = (headIndex / 32) * 32;
- 调用 arraycopy 覆盖该行:
System.arraycopy(ZERO_LINE_32, 0, buffer, eraseStart, 32); - 注意:确保 eraseStart + 32 ≤ buffer.length,否则需分段处理或用模运算绕回
注意事项与替代建议
- 性能上:arraycopy 比循环赋值快得多,尤其对大块(≥ 数十元素),因 JIT 可内联为汇编级内存操作
- 线程安全:arraycopy 是原子的,但覆盖操作本身不保证可见性;若多线程访问,需配合 volatile、synchronized 或 Unsafe.storeFence
- 更现代的选择:JDK9+ 可考虑 VarHandle.setOpaque() 或 Unsafe.setMemory()(需权限),但 arraycopy 更便携、安全、易读

















