java - 追踪 OutOfMemoryError

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

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

该应用程序并没有做任何特别的事情,但在使用 Tomcat 7 进行 2-3 次热重新部署后,我仍然收到 OutOfMemoryError。我已经完成堆转储并使用 VisualVM 打开它,这就是我所看到的:

enter image description here

如您所见,我周围有很多字符串、char[] 和 byte[]。唯一真正操纵这种数据的类是记录器,它是一个 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 配置,请随时询问。

谢谢!

最佳答案

As you can see, I'm having lots of Strings, char[] and byte[] around. The only class really manipulating this kind of data is the logger which is a servlet-filter

这真是难以置信。 hibernate 实体不包含单个字符串,HTTP 请求从不存储在 char[] 中,响应从不缓冲,...

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

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

关于java - 追踪 OutOfMemoryError,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37055102/

相关文章:

java - 如何确保@Entity存在于@Async方法中?

rest - 使用 REST 返回值

java - 从 Java 6 + Tomcat 6 升级到 Java 8 + Tomcat 8 时垃圾收集器的使用

java - 在 TomEE+ 上使用 JAX-RS 时为 "No resource methods"

java - 如何在 Web ui 中更新使用服务帐户 api 上传的 Google Drive 文档?

java - Java 的 HashMap.get 是否以任何方式修改映射?

java - Spring - 是否有可能获取所有包,并在@ComponentScan 中注册?

java - 抽象类的自定义 gson 序列化

java - 使用斯坦福 Tregex 提取子树

java - 如何调用 Spring 框架存储库方法