arrays.sort内存占用主要来自数组本体、排序临时空间和gc压力;基本类型排序几乎不新增堆内存,对象排序最多申请约1/10原数组长度的临时缓冲区;高内存水位多因装箱、comparator中创建临时对象等误用导致。

Arrays.sort 对大数组排序时,JVM 内存占用主要来自三块:数组本体存储、排序过程中的临时空间、以及 GC 压力带来的间接开销。它不额外申请与原数组同量级的堆内存,但细节决定实际水位。
数组本体始终在堆中连续存放
无论大小,int[] 或 String[] 都在堆内存中分配连续空间。例如百万级 int[](10⁶ × 4 字节 ≈ 4MB)或 String[](每个元素是引用,64位 JVM 下约 8 字节/引用,即 ~8MB 引用本身,加上字符串对象另算)。这部分是刚性占用,与 sort 无关,但它是内存压力的起点。
排序算法自身几乎不新增堆内存
双轴快排(基本类型)和 TimSort(对象数组)都是原地排序变种,仅需 O(log n) 的栈空间用于递归调用,以及少量固定大小的临时缓冲区:
- int[] 排序:内部使用小段插入排序 + 分治递归,临时变量极少,无额外对象创建
- String[] 或自定义对象数组:TimSort 会预分配一个最小长度为 32 的临时数组(run 合并用),最大可能扩展到 n/2,但 JDK 实现做了裁剪——实际最多申请约 1/10 原数组长度的临时 char[] 或 Object[] 缓冲区,且复用不重复分配
真正推高内存水位的是“误用”而非 sort 本身
多数高内存场景并非算法导致,而是周边操作引入大量临时对象或阻碍 GC:
- Integer[] 替代 int[]:百万个 Integer 对象 = 百万次装箱 → 百万级小对象分配,触发频繁 Young GC;堆内存瞬时峰值可能翻倍
- Comparator 中创建临时对象:比如 compare(a, b) 里 new SimpleDateFormat()、substring()、toLowerCase(),每次比较都生成新对象,O(n log n) 次就成了数百万对象
- 排序前未加载完成:边从文件流读取边传入 Arrays.sort,导致数据未完全驻留内存,JVM 缓存失效、GC 更频繁
- 短生命周期数组高频创建:循环中 new int[1000000] → sort → 丢弃,造成 Eden 区反复填满,Young GC 次数飙升
可观察与可控的关键点
不用猜,靠参数和工具定位真实瓶颈:
- 加 -XX:+PrintGCDetails 看是否因装箱或临时对象引发大量 GC
- 用 jstat -gc
观察 Eden、Survivor 使用率变化节奏,确认是否排序期间突增 - 对同一数组,对比 int[] 和 Integer[] 排序的堆内存增长曲线(VisualVM 或 JFR),量化装箱成本
- 避免在 Comparator 里做任何非纯计算;排序键提前缓存,如把 user.getName().length() 结果存为字段,直接比较该字段











