强引用无法避免OOM,关键在于合理使用以防内存泄漏:避免长期持有短生命周期对象、及时清理集合和监听器、慎用静态集合、复用对象而非重复创建、用弱引用或ThreadLocal替代静态强引用缓存、配合try-with-resources管理资源。

别让强引用长期绑定不该活的对象
强引用对象生命周期完全由引用链决定。如果一个本该短期存在的对象(比如Activity、临时缓存项、监听器)被静态变量、单例、线程池或长生命周期容器用强引用持有了,它就再也收不回来了。
- 禁止写 private static List<Object> cache = new ArrayList<>(); 这类无清理机制的静态集合
- 需要缓存时,改用 Caffeine 或 ConcurrentHashMap + 定期淘汰策略,而不是裸用强引用Map
- Android中尤其注意:static Context、static View 会锁死整个Activity视图树
及时切断不必要的强引用链
局部变量、方法参数、临时集合这些强引用,只要作用域结束,引用自然消失。但有些场景需要你主动干预:
- 集合中移除对象后,记得调用 list.remove(obj) —— 不是只清空内容,而是断开引用
- 监听器注册后,在合适时机(如Activity onDestroy、Fragment onDetach)调用 removeXXXListener()
- 大对象字段(如byte[]、Bitmap)使用完可显式赋 null,尤其在长生命周期对象里
避免强引用引发的对象爆炸式复制
强引用不共享,每次 new 就是一份新对象。若逻辑上多个地方该共用同一实例,却各自强引用一份,内存会指数级增长。
- 案例:自动补全索引中,为每个前缀都 new UserDTO(),1万个用户生成6万份对象 → 改用 HashSet<UserDTO> 去重,所有索引条目指向同一份实例
- 工具类中避免 static Map<String, BigObj> 缓存,改用 ThreadLocal<BigObj> 或弱引用包装
配合资源管理约束强引用的生存边界
强引用对象若包裹了外部资源(文件、连接、流),不释放资源本身也会间接导致OOM(如句柄耗尽触发假性内存错误)。
立即学习“Java免费学习笔记(深入)”;
- 一律用 try-with-resources 管理 InputStream / OutputStream / Connection 等
- 自定义资源类实现 AutoCloseable,确保 close() 中清除内部强引用缓存
- 数据库分页查大数据集时,禁用 list.stream().collect(Collectors.toList()) 全量加载,改用游标式迭代


















