Java Web 应用程序中的内存泄漏

2022-09-02 04:29:35

我有一个在Tomcat 7上运行的Java Web应用程序,它似乎有内存泄漏。在负载下(使用 JConsole 确定)时,应用程序的平均内存使用量随时间线性增加。内存使用率达到稳定值后,性能会显著下降。响应时间从~100ms到[300ms,2500ms],所以这实际上导致了真正的问题。

我的应用程序的 JConsole 内存配置文件: 应用程序内存配置文件

使用VisualVM,我看到字符数组(即char[])至少一半的内存正在使用,并且大多数(每个字符串的数量大致相同,300,000个实例)是以下之一:“分配失败”,“复制”,“次要GC结束”,所有这些似乎都与垃圾回收通知有关。据我所知,该应用程序根本不监视垃圾回收器。VisualVM 找不到这些字符串中的任何一个的 GC 根,因此我很难跟踪它。

内存分析器堆转储: 堆转储,无法访问的内存

我无法解释为什么内存使用会像这样停滞不前,但我有一个理论,为什么一旦它这样做,性能就会下降。如果内存碎片化,应用程序可能需要很长时间才能分配连续的内存块来处理新请求。

与内置的Tomcat服务器状态应用程序相比,内存会增加并处于水平,但不会像我的应用程序那样达到较高的“地板”。它也没有大量无法访问的字符[]。

Tomcat 服务器状态应用程序的 JConsole 内存配置文件: 在此输入图像描述

Tomcat 服务器状态应用程序的内存分析器堆转储p: 在此输入图像描述

这些字符串可以分配到哪里,为什么它们没有被垃圾回收?是否有 Tomcat 或 Java 设置可能会影响这一点?是否有特定的软件包可能会影响这一点?


答案 1

我从中删除了以下JMX配置:tomcat\bin\setenv.bat

set "JAVA_OPTS=%JAVA_OPTS% 
    -Dcom.sun.management.jmxremote=true 
    -Dcom.sun.management.jmxremote.port=9090
    -Dcom.sun.management.jmxremote.ssl=false
    -Dcom.sun.management.jmxremote.authenticate=false"

我无法再获得详细的内存堆转储,但内存配置文件看起来好多了:在此输入图像描述

24 小时后,内存配置文件看起来相同:在此输入图像描述


答案 2

我建议使用 memoryAnalyzer 来分析你的堆,它提供了更多的信息。
http://www.eclipse.org/mat/ 有一个独立的应用程序和一个嵌入式的eclipse。你只需要在你的应用程序上运行jmap,并用它来分析结果。


推荐