首页 > 解决方案 > 有没有办法在关闭时使用 ContextListener 在 contextDestroyed() 方法中关闭所有 ThreadLocals(保存 Session 对象)?

问题描述

我在我的应用程序中面临关于 Threadlocals 对象的内存泄漏(TOMCAT v9),如下所示:

2019 年 9 月 25 日 17:40:34.752 严重 [Thread-10] org.apache.catalina.loader.WebappClassLoaderBase.checkThreadLocalMapForLeaks Web 应用程序 [] 创建了一个 ThreadLocal,其键类型为 [java.lang.ThreadLocal](值 [java .lang.ThreadLocal@7c606bab])和类型为 [org.hibernate.internal.SessionImpl] 的值(值 [SessionImpl(56310373)]),但在 Web 应用程序停止时未能将其删除。线程将随着时间的推移而更新,以尝试避免可能的内存泄漏。

每次打开会话对象时,我都尝试关闭会话对象,但是由于缺乏编码中使用的标准,我面临着各种休眠级别的异常,因为某些对象是延迟获取的,并且关闭会话会导致意外异常。

现在,如果可能,我正在尝试使用 contextListener 来实现相同的目的,而不必担心关闭每个会话对象。

我试过使用 System.gc() 但它似乎没有释放那些 ThreadLocal 对象。

您能否建议一些方法在关闭时使用 Listener 或任何其他可能的方式摆脱这些对象?

标签: javasessiontomcatmemory-leaksthread-local

解决方案


您应该关闭 Hibernate 会话并将其从ThreadLocalWeb 请求完成时删除。

由于您在生成响应(JSP?)时似乎遇到了延迟加载问题,因此您需要在完全生成响应后执行此操作。

您可以在 Servlet 中执行此操作Filter。确保这是您拥有的任何其他过滤器之前,因此会话作为最后一步关闭。

public final class SessionCloseFilter implements Filter {
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    public void destroy() {
    }

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
        try {
            chain.doFilter(request, response);
        } finally {
            try {
                // Close and remove session here
            } catch (Exception e) {
                // Log but don't throw the exception
            }
        }
    }

}


推荐阅读