当前位置: 首页 > 知识库问答 >
问题:

spring boot(2.0.3.发行版)应用程序中的内存泄漏

靳彦
2023-03-14

我们在一个高负载(6M请求/天)的spring boot应用程序中出现了内存泄漏,它为很少的restendpoint提供服务。old_gen随时间增长缓慢,提交的内存达到容器限制,导致容器摊牌。在采取了几个堆转储后,我能够找出以下几点:

>

  • org.apache.catalina.webresources.cachedResource使用了大量内存,实例数约为12000,导致包括java.io.file在内的其他对象的数量类似。我尝试禁用tomcat缓存,虽然这些类从堆转储中消失了,但吞吐量不可避免地下降。有什么关于最佳实践的建议吗?

    spring执行器也消耗大量内存

    null

    Class Name                                                                             | Objects | Shallow Heap | Retained Heap
    --------------------------------------------------------------------------------------------------------------------------------
    org.springframework.boot.actuate.audit.InMemoryAuditEventRepository                    |       1 |           24 |  >= 5,670,928
    org.springframework.boot.actuate.audit.AuditEvent[]                                    |       1 |        4,016 |  >= 5,670,880
    org.springframework.boot.actuate.audit.AuditEvent                                      |   1,000 |       32,000 |  >= 5,666,416
    org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationDetails|   1,000 |       40,000 |  >= 5,319,552
    --------------------------------------------------------------------------------------------------------------------------------

    null

    似乎达到这个程度后就稳定了。但在这种情况下,每个请求中的对象都被替换到数组中。代码(InMemoryAuditEventrePository.java)如下所示,不确定--可能这导致了一些泄漏。

    this.events[this.tail] = event;
    

    对此有什么建议吗?禁用spring执行器?

    GC路径显示:

    null

    <pre>
    Class Name                                                                                                       | Ref. Objects | Shallow Heap | Ref. Shallow Heap | Retained Heap
    -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    org.apache.tomcat.util.net.NioBlockingSelector$BlockPoller @ 0xcadf60f8  NioBlockingSelector.BlockPoller-1 Thread|       16,884 |          136 |         1,080,576 |           920
    '- contextClassLoader org.springframework.boot.loader.LaunchedURLClassLoader @ 0xc8018578                        |       16,884 |           80 |         1,080,576 |     4,333,096
       '- classes java.util.Vector @ 0xc82b5c90                                                                      |       16,884 |           32 |         1,080,576 |     2,706,712
          '- elementData java.lang.Object[20480] @ 0xca1a5dd0                                                        |       16,884 |       81,936 |         1,080,576 |     2,706,680
             '- [7996] class com.mysql.jdbc.NonRegisteringDriver @ 0xc9b94bd8                                        |       16,884 |          112 |         1,080,576 |         7,272
                '- connectionPhantomRefs java.util.concurrent.ConcurrentHashMap @ 0xc9b94ed8                         |       16,884 |           64 |         1,080,576 |         6,528
                   '- table java.util.concurrent.ConcurrentHashMap$Node[256] @ 0xcc905b78                            |       16,884 |        1,040 |         1,080,576 |         6,464
                      |- [15] java.util.concurrent.ConcurrentHashMap$Node @ 0xcc963078                               |          504 |           32 |            32,256 |           128
                      |  '- val, key com.mysql.jdbc.NonRegisteringDriver$ConnectionPhantomReference @ 0xcbfa3840     |          504 |           32 |            32,256 |        48,504
                      |     |- discovered com.mysql.jdbc.NonRegisteringDriver$ConnectionPhantomReference @ 0xcbb4ec50|          378 |           32 |            24,192 |        48,504
                      |     |- referent com.mysql.jdbc.JDBC4Connection @ 0xcc080018                                  |          126 |        1,232 |             8,064 |        32,024
                      |     '- Total: 2 entries                                                                      |              |              |                   |              
    -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    null

    有线索吗?

    null

    <pre>
    Class Name                                        | Objects | Shallow Heap
    ---------------------------------------------------------------------------
    char[]                                            |  21,936 |    1,988,712
    int[]                                             |  13,191 |    1,913,760
    java.lang.Object[]                                |  12,230 |      652,176
    java.lang.String                                  |  21,936 |      526,464
    java.lang.reflect.Method                          |   2,994 |      263,472
    java.lang.ref.SoftReference                       |   4,051 |      162,040
    java.util.LinkedHashMap$Entry                     |   3,873 |      154,920
    java.util.HashMap$Node[]                          |   2,470 |      142,784
    java.util.LinkedHashMap                           |   2,314 |      129,584
    java.lang.reflect.Constructor                     |   1,133 |       90,640
    sun.reflect.generics.tree.SimpleClassTypeSignature|   2,776 |       66,624
    java.util.ArrayList                               |   2,735 |       65,640
    ---------------------------------------------------------------------------

    null

    有谁能建议一下如何看到这些对象的价值(使用MAT),如何追踪?

    还有其他建议吗?

  • 共有1个答案

    蓟浩旷
    2023-03-14

    分析了堆转储之后,是否真的存在任何内存泄漏或者这是JVM的通常行为并不十分明显。我们在oracle jre 8中使用docker映像,它上次更新是在2年前。我们更改为openjdk,现在内存行为似乎更加稳定。

     类似资料:
    • 我有一个运行在Tomcat7上的Java web应用程序出现内存泄漏。在负载下(使用JConsole确定),应用程序的平均内存使用量随时间线性增加。在内存使用达到稳定期后,性能会显著下降。响应时间从大约100ms到[300ms,2500ms],所以这实际上导致了真正的问题。 使用VisualVM,我看到至少一半的内存被字符数组(即char[])使用,而且大多数字符串(每个实例的数量大致相同,为30

    • 我在spring引导应用程序中面临内存泄漏,在使用Eclipse MAT进行堆转储分析之后,它指出了spring boot执行器中潜在的内存:精确地说是使用InMemoryAuditEventRepository(审计事件)。 禁用此内存审核事件的最佳方法是什么: 删除spring-boot-acturtor依赖项 management.endpoints.enabled-by-default=t

    • 我看到了这个Python问题:应用引擎延迟:跟踪内存泄漏 ...同样,我也遇到了这个可怕的错误: 在为总共384个请求提供服务后,超过了128 MB的软专用内存限制 ... 处理此请求后,发现处理此请求的进程占用了太多内存,因此被终止。这可能会导致应用程序的下一个请求使用新进程。如果经常看到此消息,则应用程序中可能存在内存泄漏。 根据另一个问题,可能是“实例类”太小,无法运行这个应用程序,但是在增

    • 问题内容: 我看到了这个Python问题:推迟了AppEngine:跟踪内存泄漏 …同样,我遇到了这个可怕的错误: 总共为384个请求提供服务后,超出了128 MB的软私有内存限制 … 处理此请求后,发现处理此请求的进程使用了​​过多的内存并被终止。这很可能导致新流程用于您的应用程序的下一个请求。如果您经常看到此消息,则可能是应用程序内存泄漏。 根据另一个问题,可能是“实例类”太小而无法运行此应用

    • 我使用石英版和Spring Boot版。它表现正常,一切正常。但是当我试图关闭这个应用程序时,问题出现了。日志显示有内存泄漏... 我的石英配置; 我有两个班,执行如下工作; 另一个班也同样做着不同的事情。 调度器工厂Bean如下; 我得到了像下面这样的tomcat日志; 查阅了quartz文档,并在properties中添加了以下内容:; 第一条线程消息消失了,但关于worker-2的第二条消息

    • 我有以下代码试图在一个大表上循环(~100k行;~30GB) 但是,我不断遇到以下错误: 处理此请求时,发现处理此请求的进程占用了太多内存,因此终止。这可能会导致应用程序的下一个请求使用新进程。如果经常看到此消息,则应用程序中可能存在内存泄漏。 ...有时候...... 在处理总共9个请求后,超过了128 MB的软私有内存限制,达到154 MB 我改变了我的代码,所以我总是在任何给定的时间只提取1