追踪OutOfMemoryError

时间:2016-05-05 16:00:44

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

我在尝试追踪这个OutOfMemoryError时非常糟糕,我真的很感激一些帮助。我的应用程序分为体系结构部分和一个模块,该模块使用Hibernate创建的数据库CRUD操作公开一些基本的REST WS。主体系结构具有记录和管理属性和配置的唯一作用(所有这些都由Spring处理)。

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

enter image description here

正如您所看到的,我有很多字符串,char []和byte []。真正操纵这种数据的唯一类是记录器,它只是一个servlet过滤器:

@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配置,请随时询问。

谢谢!

2 个答案:

答案 0 :(得分:0)

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

这里有一个很好的解释:

What makes hot deployment a "hard problem"?

答案 1 :(得分:0)

  

正如你所看到的,我有很多字符串,char []和byte []。真正操纵这种数据的唯一类是记录器,它是一个servlet-filter

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

字符串是一种普遍存在的数据类型,几乎每个类路径中的每个库都会广泛使用它们,诀窍在于找到哪个库正在泄漏​​它们,以及原因。

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