避免大对象分配导致内存溢出,关键在于不一次性申请超大内存块、分块处理、精简对象结构、合理使用软/弱引用及及时释放无效引用。

大对象分配导致内存溢出,核心在于避免一次性申请超大内存块(如巨型数组、超长字符串、大批量实体集合),同时切断其隐式生命周期延长。优化重点不是“扛住”,而是“不这么干”。
避免在循环或高频路径中直接 new 大对象
比如 new byte[1024 * 1024] 或 new ArrayList(100000),尤其在 while(true) 或高并发请求中,会迅速填满堆空间。
- 改用分块处理:读取文件时不用一次性 loadAll(),而用
BufferedInputStream配合固定大小 buffer(如 8KB)流式读取 - 数据库查询禁用
SELECT * FROM huge_table,改成分页(LIMIT/OFFSET或游标式查询),或启用 JPA 的@Query(..., fetch = FetchType.LAZY) - 构造集合前预估容量,避免多次扩容;若数量固定且不大,直接用数组替代
ArrayList
精简大对象内部结构与引用关系
一个“大对象”往往不是单个实例大,而是它间接持有的对象树太深、太宽。
- 检查 DTO/VO 类是否包含冗余字段(如带完整关联对象的嵌套 JSON 字符串),只保留当前业务必需字段
- 避免在大对象中持有
static或长生命周期容器(如缓存 Map、监听器列表),防止 GC 无法回收整棵引用链 - 使用基本类型数组(
int[])代替包装类集合(List<integer></integer>),省去每个元素的对象头和装箱开销
用对引用类型管理缓存类大对象
如果必须缓存图片、解析结果、模板等大对象,不能靠强引用死守,要让 JVM 在内存紧张时能主动释放。
- 优先选
SoftReference:适合“可丢弃但尽量保留”的场景(如缩略图缓存),JVM 内存不足时自动回收 - 慎用
WeakReference:适合临时映射(如 ThreadLocal 中的上下文快照),GC 每次都可能回收 - 生产环境推荐成熟缓存库(如 Caffeine),它自带大小限制、过期策略和弱键/软值支持,比手写 Map + Reference 更可靠
及时切断无效引用链
很多 OOM 表面是“分配大对象失败”,实际是老对象一直被意外持有,腾不出空间给新对象。
- 静态集合(
static List<object></object>)必须配套清理机制,或改用WeakHashMap存储回调监听器 - 使用完
InputStream/ResultSet后务必 close,最好用 try-with-resources;未关闭会导致底层缓冲区长期驻留 - 异步任务提交后,检查是否意外持有 Handler、Context(Android)、或闭包中的大对象引用,尤其注意 lambda 表达式捕获的外部变量
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











