ARTIFACTORY:遇到一个未计算的高内存使用Java?这里有一些关于如何诊断和调整的提示
如果在Java内存图中遇到内存使用稳步增长的情况,
或者,例如,遇到类似的场景,如:
- 系统配置20gb RAM
- Java堆占内存的65%,即13gb (Xmx=13g)
- 运行一段时间后,内存被填满,java RSS使用量显示19gb的使用量(这意味着有6gb的堆外内存—对于任何大小,预期的堆外内存使用量都低于1gb)。
最好将这些Java图表添加到统计数据中,以便能够确定增长的来源:
有几件事你应该验证,以支持理论,你正在处理堆外内存增长:
Pid user pr ni virt res SHR s % cpu % mem time +命令
XXX根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已收集
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输出的例子:Num #instances #bytes类名(module)
-------------------------------------------------------
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)
类(预留=390942KB +6691KB,提交=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)
(栈:reserved=1909532KB +626052KB, committed=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)
编译器(预留=11553KB +4492KB,提交=11553KB +4492KB)
(malloc=11420KB +4492KB #7690 +1681)
(舞台= 133 kb # 5)
内部(预留=81594KB +24067KB,提交=81594KB +24067KB)
(malloc=81562KB +24067KB #33110 +8076)
(mmap: reserved=32KB, committed=32KB)
其他(reserved=666518KB +3121KB, committed=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
