【问题标题】:Tracking down OutOfMemoryError追踪 OutOfMemoryError
【发布时间】:2016-08-31 12:10:28
【问题描述】:

我在试图追踪这个 OutOfMemoryError 时遇到了非常糟糕的情况,我非常感谢一些帮助。我的应用程序分为架构部分和一个模块,该模块公开了一些基本的 REST WS 以及 Hibernate 进行的数据库 CRUD 操作。主架构的唯一作用是记录和管理属性和配置(所有这些都由 Spring 处理)。

应用程序没有做任何花哨的事情,但在使用 Tomcat 7 进行 2-3 次热重新部署后,我仍然收到 OutOfMemoryError。我做了一个堆转储并用 VisualVM 打开它,这就是我看到的:

如您所见,我周围有很多字符串、char[] 和 byte[]。唯一真正操作此类数据的类是 logger,它是一个 servlet-filter,仅执行此操作:

@Override
public void doFilter(ServletRequest request, ServletResponse response,
        FilterChain chain) throws IOException, ServletException {

        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        HttpServletResponse httpServletResponse = (HttpServletResponse) response;

        Map<String, String> requestMap = this
                .getTypesafeRequestMap(httpServletRequest);
        BufferedRequestWrapper bufferedRequest = new BufferedRequestWrapper(
                httpServletRequest);
        BufferedResponseWrapper bufferedResponse = new BufferedResponseWrapper(
                httpServletResponse);

        final StringBuilder logMessage = new StringBuilder(
                "REST Request - ").append("[HTTP METHOD:")
                .append(httpServletRequest.getMethod())
                .append("] [PATH INFO:")
                .append(httpServletRequest.getRequestURI())
                .append("] [REQUEST PARAMETERS:").append(requestMap)
                .append("] [REQUEST BODY:")
                .append(bufferedRequest.getRequestBody())
                .append("] [REMOTE ADDRESS:")
                .append(httpServletRequest.getRemoteAddr()).append("]");
        long startTime = System.currentTimeMillis();
        chain.doFilter(bufferedRequest, bufferedResponse);
        long elapsed = System.currentTimeMillis() - startTime;
        logMessage.append(" [RESPONSE:")
                .append(bufferedResponse.getContent())
                .append("] [ELAPSED TIME:").append(elapsed).append("ms]");
        log.debug(logMessage.toString());
}

如果记录器不是造成这种情况的原因,可能是由于某些我不知道的 Spring/Hibernate/Tomcat/某些库造成的吗?

如果您需要其他任何东西,例如 Spring 配置,请随时提出。

谢谢!

【问题讨论】:

  • 你的tomcat内存设置是什么(Xmx、PermSize)?
  • 当 Tomcat 作为应用程序服务器启动时,您是否尝试为您的 Web 应用程序分配更多内存?还要尝试弄清楚“支配对象”是否创建并保存了许多引用(我遇到过 Hibernate 是原因的情况)

标签: java spring tomcat memory-leaks out-of-memory


【解决方案1】:

如您所见,我周围有很多字符串、char[] 和 byte[]。唯一真正操作此类数据的类是 logger,它是一个 servlet-filter

这真的很难相信。 hibernate 实体不包含单个字符串,HTTP 请求永远不会存储在 char[] 中,响应永远不会缓冲,...

字符串是一种无处不在的数据类型,几乎你的类路径中的每个库都会广泛使用它们,诀窍是找出哪个库泄漏了它们,以及为什么。

要有效地分析堆转储,您应该使用一种工具,该工具不仅可以列出有多少对象,还可以分析对象引用图以找出哪些对象使这些字符串保持活动状态。大多数商业内存配置文件都能很好地做到这一点。除此之外,开源Eclipse Memory Analyzer 也相当不错。自从我上次使用它已经有一段时间了,但是对于我上次的内存泄漏,MAT 的标准泄漏嫌疑报告正确地识别出导致 OutOfMemoryError 的对象。

【讨论】:

    【解决方案2】:

    该问题与 JEE webapps 的热重新部署有关。不在 Tomcat 中,而是在任何 JEE Servlet 容器中。

    这里有一个很好的解释:

    What makes hot deployment a "hard problem"?

    【讨论】:

    • 除了作为仅链接的答案之外,该博客文章似乎已经过时了。具体来说,它要求设置一个 Java 8 不再存在的 JVM 参数,而 Java 7 已经停产一年多...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-10-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多