Spring Boot(2.0.3.RELEASE)应用程序中的内存泄漏

时间:2019-01-17 16:17:18

标签: java spring-boot memory-leaks

我们在高负载(每天6m req /天)的Spring Boot应用程序中发生内存泄漏,仅服务于很少的其余端点。 old_gen随时间增长缓慢,并且已提交的内存达到容器限制,从而导致容器摊牌。 经过几次堆转储后,我发现了以下内容:

  1. org.apache.catalina.webresources.CachedResource使用了大量的内存,实例计数约为12000,从而导致其他对象(包括java.io.File)的数量类似。我尝试禁用tomcat缓存,尽管这些类已从heapdump中删除,但吞吐量不可避免地降低了。 对最佳做法有何建议?

  2. 弹簧执行器也消耗大量内存

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
--------------------------------------------------------------------------------------------------------------------------------

达到此水平后似乎稳定。但是在那种情况下,对于每个请求,对象都会在数组中被替换。代码(InMemoryAuditEventRepository.java)如下所示,不确定-可能会导致一些泄漏。

this.events[this.tail] = event;

对此有何建议?禁用弹簧执行器?

    此类的
  1. 17670个实例:org.springframework.security.access.method.DelegatingMethodSecurityMetadataSource $ DefaultCacheKey。也像上课一样稳定。似乎与缓存有关。
  2. 20000个com.mysql.jdbc.ConnectionPropertiesImpl $ BooleanConnectionProperty实例!

GC的路径显示:

<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                                                                      |              |              |                   |              
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

有任何线索吗?

  1. 堆转储还显示了一些无法访问的对象。计数128,249消耗7MB,主要是:

<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
---------------------------------------------------------------------------

有人可以建议如何查看这些对象的值(使用MAT),如何进行跟踪?

还有其他建议吗?

1 个答案:

答案 0 :(得分:0)

在分析了堆转储之后,如果实际上存在任何内存泄漏或者这是JVM的通常行为,则不太明显。 我们将docker image与oracle jre 8一起使用,该镜像最近更新于2年前。我们更改为openjdk,现在内存行为似乎更加稳定。