JAVA/FLEX应用程序内存泄漏问题排查咨询
内存泄漏排查步骤(针对Timer线程未终止问题)
从日志可以明确问题:Web应用gboxc_ccy启动的Timer-0线程在应用停止时未被终止,导致Tomcat的WebappClassLoader无法被回收,引发内存泄漏。具体排查方向如下:
定位
java.util.Timer的创建位置
搜索代码中所有new Timer()的调用,因为默认情况下Timer创建的线程命名规则是Timer-N(N从0开始),找到创建Timer-0的具体代码位置,重点检查:- Servlet上下文初始化逻辑(如
ServletContextListener的contextInitialized方法) - Spring Bean的初始化方法(如
@PostConstruct) - 业务代码中手动创建Timer的场景
- Servlet上下文初始化逻辑(如
检查Timer的销毁逻辑
java.util.Timer必须调用cancel()方法才能终止内部的TimerThread,否则线程会一直处于WAITING状态(对应日志里的TimerThread.mainLoop堆栈)。需要确认:- 是否在应用关闭的回调中执行了
timer.cancel():比如Spring Bean的@PreDestroy方法、Servlet的destroy()方法、Spring的ContextClosedEvent监听逻辑 - 所有创建的Timer实例都有对应的销毁操作,没有遗漏
- 是否在应用关闭的回调中执行了
排查第三方依赖中的Timer使用
检查项目依赖的第三方组件(如定时任务库、消息队列客户端、工具类库)是否内部使用了java.util.Timer且未正确处理生命周期。可以通过:- 分析完整线程dump(如果有更多线程信息),查看是否有其他关联线程指向第三方库
- 查看依赖库的文档或源码,确认其定时任务的销毁机制
替换为更安全的定时任务实现(推荐)
java.util.Timer本身存在单线程、未正确销毁会泄漏的缺陷,建议替换为:- JDK自带的
ScheduledExecutorService,通过shutdown()或shutdownNow()可以安全终止所有任务 - Spring环境下使用
@Scheduled注解配合Spring任务调度器,Spring会在容器关闭时自动清理定时任务
- JDK自带的
内容的提问来源于stack exchange,提问作者Mouad Harhar
相关产品推荐
相关产品推荐

