Vaadin-view作用域(Tagetik定制)下内存泄漏问题咨询
排查思路与建议
Mother能被正常回收但Son对象始终无法释放,核心原因是Son存在Mother之外的其他强引用持有,导致其引用链未被切断,可以从以下方向排查:
可能的触发场景
- 全局/单例对象持有Son引用:
如果Son中注册了Vaadin UI事件监听器、Spring事件监听器,或者启动了定时任务但未取消,这些全局容器(事件总线、线程池)会持续持有Son的引用;另外若Son被添加到单例Bean的集合、缓存中,也会被长生命周期对象绑定。 - Vaadin上下文隐式引用:
若Son实现了Vaadin的Component接口,或被误添加到UI组件树、Vaadin Session属性中(比如UI.getCurrent().add()、VaadinSession.getCurrent().setAttribute(...)),Mother关闭后这部分上下文资源未清理,会持续持有Son。 - 未释放的资源或ThreadLocal:
Son若打开了IO流、数据库连接等资源未关闭,底层资源对象可能持有Son引用;另外Son使用ThreadLocal存储自身数据时,若对应线程(如Tomcat线程池线程)长期存活,ThreadLocal的Entry会绑定Son。 - 非静态内部类关联(低概率):
若Son是Mother的非静态内部类,即便Mother被回收,若Son还被其他外部对象持有,也会无法释放(不过这种情况Mother通常也会被牵连,所以概率较低)。
具体排查步骤
- 用内存分析工具定位引用链:
用MAT(Memory Analyzer Tool)或VisualVMdump堆内存,找到Son的实例,查看Path to GC Roots(过滤弱/软引用),直接定位到持有Son的对象,这是最直接的排查方式。 - 检查Son的代码逻辑:
逐行梳理Son的代码,排查是否存在注册监听器、定时任务、ThreadLocal的逻辑,是否关联到Vaadin的UI/Session,是否有未关闭的资源。 - 补充Mother的销毁清理动作:
给Mother添加@PreDestroy方法,在其中手动清理Son的相关引用(比如注销监听器、关闭资源、移除Session属性),验证是否能触发Son的回收。 - 追踪Son的传递路径:
确认除了Mother构造方法外,是否有将Son传递给其他长生命周期对象(单例Bean、Session作用域对象)的逻辑。
内容的提问来源于stack exchange,提问作者Marco Terrosi
相关产品推荐
相关产品推荐

