我们在高负载(每天6m req /天)的Spring Boot应用程序中发生内存泄漏,仅服务于很少的其余端点。 old_gen随时间增长缓慢,并且已提交的内存达到容器限制,从而导致容器摊牌。 经过几次堆转储后,我发现了以下内容:
org.apache.catalina.webresources.CachedResource使用了大量的内存,实例计数约为12000,从而导致其他对象(包括java.io.File)的数量类似。我尝试禁用tomcat缓存,尽管这些类已从heapdump中删除,但吞吐量不可避免地降低了。 对最佳做法有何建议?
弹簧执行器也消耗大量内存
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;
对此有何建议?禁用弹簧执行器?
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 | | | |
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
有任何线索吗?
<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),如何进行跟踪?
还有其他建议吗?
答案 0 :(得分:0)
在分析了堆转储之后,如果实际上存在任何内存泄漏或者这是JVM的通常行为,则不太明显。 我们将docker image与oracle jre 8一起使用,该镜像最近更新于2年前。我们更改为openjdk,现在内存行为似乎更加稳定。