You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

创建10万容量Java ArrayList后空闲内存增加异常排查求助

为啥创建ArrayList后空闲内存反而增加了?

嗨,这个问题我当初做集合性能对比时也碰到过,一开始完全摸不着头脑,后来搞清楚是JVM内存管理的几个隐性细节在作祟,咱们来拆解下:

核心原因:隐性触发的垃圾回收(GC)

你看到的“空闲内存增加”,本质是JVM在两次内存测量之间自动执行了GC,而且回收的临时对象内存,比ArrayList分配的内存还要多。

看你的输出数据:

Total memory: 514850816 bytes Free memory: 511852088 bytes Used memory: 2998728 bytes
...
Total memory: 514850816 bytes Free memory: 512526416 bytes Used memory: 2324400 bytes

创建ArrayList前后,已用内存从2.86MB降到了2.22MB,说明GC回收了至少600KB以上的内存——而你创建的容量100000的ArrayList,如果存储的是对象引用(64位JVM下每个引用8字节),总占用才800KB左右,回收的内存比分配的还多,自然空闲内存就上升了。

容易忽略的细节补充

1. ArrayList的容量预分配没你想的那么“重”

new ArrayList(100000)只是分配了一个能装100000个元素的数组,但数组里存的是对象引用(不是对象本身)。如果你的元素还没被填充,这个数组占用的内存其实很小——100000 * 8字节 = 800KB,这点内存很容易被GC回收的其他内存覆盖。

2. 手动内存测量的局限性

Runtime.getRuntime()的内存方法是即时快照,而且JVM有很多内存优化(比如TLAB本地线程分配缓冲、堆内存的动态调整),单次测量的误差很大。比如,JVM可能会把之前预留的“空闲但未使用”的内存划给ArrayList,而不是直接从已用内存里扣,这也会让freeMemory的数值看起来有波动。

验证和优化建议

  • 测试时手动触发GC(仅用于调试):在两次内存测量前调用System.gc(); Thread.sleep(100);(虽然GC不能保证立刻执行,但能提高概率),这样能减少GC时机的干扰,更准确地看到ArrayList的内存占用。
  • 多次测量取平均值:单次快照偶然性太大,多测几次取平均,结果会更可靠。
  • 用专业工具替代手动测量:比如JProfiler、VisualVM,或者用JMH做基准测试——这些工具能精准监控对象分配、GC事件,避免手动测量的误差。

内容的提问来源于stack exchange,提问作者ProfPlum

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 04:02:12