开发中遇到程序越来越卡,响应变慢,甚至频繁崩溃?很可能是因为内存泄漏在悄悄作祟。别急着重装系统或者换电脑,用好 IntelliJ IDEA 自带的工具,就能快速定位问题。
打开内存视图,一眼看出异常
在 IDEA 中运行 Java 应用时,右下角有个小面板叫 “Memory”。点击启用后,你会看到实时的堆内存使用曲线。如果发现内存占用一路飙升,垃圾回收(GC)过后也没明显回落,那基本可以怀疑有对象没被正确释放。
抓取堆转储,锁定可疑对象
当内存异常时,直接点击 Memory 面板旁边的垃圾桶图标旁的堆快照按钮,就能生成一个 .hprof 文件。这个文件记录了当前所有存活对象的信息。IDEA 会自动用内置的堆分析器打开它。
进入堆分析界面后,点开 “Dominator Tree” 或直接搜索你怀疑的类名。比如某个用户管理模块反复加载但从未释放,你可能会看到 UserSessionManager 相关的对象数量多得离谱。这时候点进去,查看具体实例的引用链,就能看到是谁一直 holding 着它们不放。
常见泄漏场景:监听器忘了注销
比如你在界面上注册了一个事件监听,但切换页面后没取消注册。这个监听器持有了 Activity 或 Controller 的引用,导致整个页面无法被回收。在堆分析里,你会看到匿名内部类如 MyFrame$1 占用了大量内存,而它的 GC Root 路径指向了全局事件总线。
eventBus.register(this); // 注册了但忘了 unregister
静态集合惹的祸
另一个典型问题是静态 Map 缓存不断添加,却不清除。比如:
public class CacheHolder {
private static Map<String, Object> cache = new HashMap<>();
public static void put(String key, Object value) {
cache.put(key, value);
}
}
这种写法短期内没问题,时间一长,缓存越积越多。在堆分析中,你会发现这个静态 map 成为多个大对象的 GC Root,直接拖垮内存。
利用 IDEA 的 Leak Suspects 报告
分析 .hprof 时,IDEA 通常会在顶部自动生成一份 “Leak Suspects” 报告。它会用通俗语言告诉你:“发现 85% 的内存被 java.util.Vector 占据,可能存在问题。” 点进去看详情,往往能快速缩小排查范围。
对比多次快照,看清增长趋势
单次快照只能看状态,多次快照才能看出变化。建议在应用启动后、执行某操作后、再执行一次后,分别抓三次快照。在 IDEA 的堆分析器里对比它们,如果某个类的实例数从 10 增加到 1000,那这个类大概率就是元凶。
小技巧:给对象加标识便于追踪
调试阶段可以在关键对象的构造函数里打上日志,输出 this.hashCode(),这样在堆转储里看到具体实例时,能快速对应到代码逻辑中的哪一次创建。比如:
public UserSession() {
System.out.println("UserSession created: " + this.hashCode());
}
结合日志和堆快照,排查效率翻倍。