System.arraycopy不能直接拷贝多维数组整体或保障高并发一致性,正确做法是逐行深拷贝、扁平化存储、volatile引用替换及统一Object[][]类型收口。

System.arraycopy 本身不直接支持多维数组的“整体拷贝”,更不解决高并发下的数据一致性问题。它只是底层内存块搬运工,用错场景或方式,反而会导致报表字段缺失、行列错位、甚至静默丢数据。要确保多维报表动态拼装时“数据不缩水”,关键不是堆 arraycopy 调用,而是在正确层级、正确时机、用正确参数做精准迁移。
多维数组本质是数组的数组,不能直接 arraycopy 整体
Java 中所谓“二维数组”(如 int[][])其实是一维引用数组,每个元素指向一个独立的一维数组(如 int[])。System.arraycopy(src, 0, dest, 0, length) 只能复制这一层的引用,不会递归拷贝子数组内容。
▶ 错误写法:
int[][] dataOld = {{1,2}, {3,4}};
int[][] dataNew = new int[5][];
System.arraycopy(dataOld, 0, dataNew, 0, dataOld.length); // 只复制了两个引用
// dataNew[0] 和 dataNew[1] 指向原数组,dataNew[2]~[4] 是 null —— 表格行数“缩水”✅ 正确做法:按需逐层控制
- 若拼装的是固定结构报表(如每行 8 列,共 N 行),应使用扁平化一维数组(
int[] flat = new int[N * 8]),用arraycopy搬整块连续内存,零开销、无引用干扰; - 若必须用
int[][],则对每一行单独判断并拷贝:for (int i = 0; i < src.length && i < dest.length; i++) { if (src[i] != null) { dest[i] = new int[src[i].length]; System.arraycopy(src[i], 0, dest[i], 0, src[i].length); } }
高并发下防“数据缩水”的核心是隔离+原子替换
报表拼装常涉及多个线程往同一汇总结构追加数据(如按维度聚合后写入结果表)。此时若多个线程共用一个 int[][] result 并直接 arraycopy 写不同行,会出现:
- 线程 A 写
result[100],线程 B 同时写result[101]→ 表面安全; - 但若
result本身正在扩容(比如从new int[100][]扩到new int[200][]),而线程未同步就写入旧数组 → 新增行丢失,“数据缩水”。
✅ 推荐模式:新数组 + volatile 引用替换
private volatile int[][] reportData = new int[INIT_ROWS][]; // 拼装线程中(不直接改 reportData) int[][] snapshot = reportData; int[][] newData = Arrays.copyOf(snapshot, snapshot.length + addRows); // 用 arraycopy 把原有有效行完整搬过去(按实际 size,非 length!) System.arraycopy(snapshot, 0, newData, 0, Math.min(snapshot.length, currentSize)); // 再把新增行逐个填入 newData[currentSize]... reportData = newData; // 原子发布,所有线程下次读到完整视图
动态列扩展时,避免因类型/长度校验失败导致截断
报表常需动态增列(如新增“同比增幅”列),此时若用 Object[][] 存储混合类型,再试图 arraycopy 到 String[][] 或 Number[][],会立即抛 ArrayStoreException——不是丢数据,是直接失败。
✅ 安全做法:
- 统一用
Object[][]作为拼装底层数组(兼容任意列类型); - 列扩展时,创建新
Object[newCols]数组,用arraycopy复制旧列,再手动设置新列位置; - 导出前再按需转换(如调用
toString()或格式化),不依赖arraycopy做类型转换。
小结:不缩水 = 不越界、不丢行、不混型、不覆盖
- ✅ 目标数组长度 ≥ 实际需拷贝的行数(不是声明长度);
- ✅ 每行子数组单独创建、单独
arraycopy,不复用源子数组引用; - ✅ 并发写入走“新建+替换”路径,不就地修改共享数组;
- ✅ 类型统一收口在
Object[][],导出阶段再转换,避开arraycopy的类型强约束。
真正拉开报表稳定性的,从来不是拷贝快慢,而是你是否让每一份数据都落在它该在的位置上。

















