ARTIFACTORY:遇到Java未解释的高内存使用?-这里有一些关于如何诊断和调优的提示
如果您在Java内存图中遇到内存使用的稳定增长,
或者举个例子,遇到类似的场景:
- 系统配置20gb RAM
- Java堆占RAM的65%,即13gb (Xmx=13g)
- 运行一段时间后,内存被填满,java RSS使用显示为19gb的使用(这意味着有6gb的堆内存-预期的堆内存使用对于任何大小都低于1gb)。
将这些Java图形添加到您的统计数据中是很好的,以便能够确定增长来自哪里:
您应该验证以下几件事,以支持您正在处理Off-Heap内存增长的理论:
Pid user pr ni virt res SHR s % cpu % mem time +命令
XXX root 20 0 146.4g 118.6g 8724 S 411.1 62.9 91897:38 java
root 20 0 892316 3748 1280 S 38.9 0.0 6453:21 collectd
root 20 0 162652 2584 1512 R 16.7 0.0 0:00.07 top
root 20 0 7010468 81116 8660 S 5.6 0.0 14640:08 jf-router
再次运行top命令来验证RES的使用是在减少还是只随着时间的推移而增加。
2.你可以生成一个完整的堆转储(对于小堆大小,这是一个有效的选项),或者使用更轻的命令,如jmap-histo,来验证堆中的顶级内存消费类,这里是一个jmap-histo输出的例子:类名称(模块)
-------------------------------------------------------
1: 183948116 20051625016 [B (java.base@11.0.10)]
2: 107411561 10480182648 [Ljava.lang.Object;(java.base@11.0.10)
3: 14622663 4640754192 [I (java.base@11.0.10)
4: 66011886 3696665616 java.io.ObjectStreamClass$WeakClassKey
5: 67176598 2149651136 java.lang.String (java.base@11.0.10)
6: 8447 1625706088 [Ljava.io.ObjectInputStream$HandleTable$HandleList;
如果您的堆总大小小于JVM内存使用指标,例如,如果堆大小只有50g,而内存消耗达到100g,这可能意味着内存增加与堆外使用有关,而不是与堆上使用有关。
3.可以使用以下3个命令监视离堆使用情况XX: NativeMemoryTracking =细节
jcmd
jcmd
本机内存跟踪的输出示例:Total: reserved=112659368KB +849436KB, committed=110938608KB +311636KB
Java堆(预留=104857600KB,已提交=104857600KB)
(mmap: reserved=104857600KB, committed=104857600KB)
类(reserved=390942KB +6691KB, committed=389834KB +6179KB)
(班级#67968 +629)
(实例类#65290 +621,数组类#2678 +8)
(malloc=14110KB +547KB #236512 +4073)
(mmap: reserved=376832KB +6144KB, committed=375724KB +5632KB)
(元数据)
(保留= 0 kb,承诺= 0 kb)
(= 0使用kb)
(自由= 0 kb)
(浪费= 0 kb =南%)
线程(预留=1918398KB +628973KB,已提交=226478KB +84781KB)
(线程#1858 +609)
(堆栈:预留=1909532KB +626052KB,已提交=217612KB +81860KB)
(malloc=6690KB +2208KB #11150 +3654)
(竞技场=2176KB +714 #3715 +1218)
(malloc=14554KB +209KB #34757 -4963)
(mmap: reserved=247684KB, committed=219952KB +6904KB)
GC(预留=4275279KB +71298KB,已提交=4275279KB +71298KB)
(malloc=346483KB +71298KB #180670 +19138)
(mmap: reserved=3928796KB, committed=3928796KB)
编译器(reserved=11553KB +4492KB, committed=11553KB +4492KB)
(malloc=11420KB +4492KB #7690 +1681)
(舞台= 133 kb # 5)
内部(预留=81594KB +24067KB,已提交=81594KB +24067KB)
(malloc=81562KB +24067KB #33110 +8076)
(mmap: reserved=32KB, committed=32KB)
其他(预留=666518KB +3121KB,已提交=666518KB +3121
如你所见malloc每个内存域的值都在增加,如果你取两个
更多的NMT跟踪,看到这个值仍然在增加,我们建议调整这个设置如下:
在系统中设置这个环境变量:export MALLOC_ARENA_MAX=<2 x (# ofCPU Cores)>
MALLOC_ARENA_MAX设置使用的最大内存池数量,与内核数量无关
默认设置是8倍的核数,我们建议先减少到几个机器的核(如果机器有16个核,设置为32),如果你想减少它,甚至更多,尝试逐渐减少,看看它是否有效果(减少到太低会影响CPU性能,所以请考虑)。
下面是一些你可以用来阅读Java内存使用设置的参考:
https://blog.malt.engineering/java-in-k8s-how-weve-reduced-memory-usage-without-changing-any-code-cbef5d740ad
https://newbedev.com/growing-resident-memory-usage-rss-of-java-process
https://blog.picnic.nl/quest-to-the-os-java-native-memory-5d3ef68ffc0a