java内存优化-之一

最近开始优化线上整个微服务的内存使用了。本来是通过抓取spring boot的metric来进行绘图查看,后来sy搞了个jconsle,这样画出来的东西就更多了。

但是之前我们都是用nmt来查看的。首先是打开服务的nmt

1
-XX:NativeMemoryTracking=summary

默认选项为 off(默认), summary, detail 这3个选项,看名字就知道大概含义了,一般我们就summary就够了。

然后使用jcmd就可以查看整个nmt的构成了

1
jcmd 18050 VM.native_memory summary scale=MB

使用方法很多,这里就不一一说了。
我们使用的args如下

1
-Xms250m -Xmx250m -Xss256k -XX:MaxMetaspaceSize=128m -Dhttp.maxConnections=100 -XX:NativeMemoryTracking=summary

然后使用jcmd得到如下的结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
jcmd 25998 VM.native_memory scale=MB summary
25998:

Native Memory Tracking:

Total: reserved=1669MB, committed=447MB
- Java Heap (reserved=250MB, committed=250MB)
(mmap: reserved=250MB, committed=250MB)

- Class (reserved=1093MB, committed=76MB)
(classes #12362)
(malloc=11MB #21119)
(mmap: reserved=1082MB, committed=65MB)

- Thread (reserved=21MB, committed=21MB)
(thread #40)
(stack: reserved=20MB, committed=20MB)

- Code (reserved=252MB, committed=47MB)
(malloc=8MB #9948)
(mmap: reserved=244MB, committed=39MB)

- GC (reserved=19MB, committed=19MB)
(malloc=10MB #246)
(mmap: reserved=9MB, committed=9MB)

- Internal (reserved=12MB, committed=12MB)
(malloc=11MB #14550)

- Symbol (reserved=16MB, committed=16MB)
(malloc=13MB #140923)
(arena=3MB #1)

- Native Memory Tracking (reserved=3MB, committed=3MB)
(tracking overhead=3MB)

- Arena Chunk (reserved=3MB, committed=3MB)
(malloc=3MB)

可以看到,我设置了maxmetaspace是128M,可为什么NMT里显示class metaspace申请了1093M,而这个进程我总共就分配了512M,这一旦超了马上就oom了。

根据https://stackoverflow.com/questions/54250638/is-compressedclassspacesize-area-contains-maxmetaspacesize-area 上说的

1
committed(Non-class Metaspace) + committed(Compressed Class Space) <= MaxMetaspaceSize

这样应该是MaxMetaspaceSize是会大于CompressedClassSpaceSize的。但是我们总是要试一下啊,于是用下列参数又重启了一下

1
-Xms250m -Xmx250m -Xss256k -XX:CompressedClassSpaceSize=128m -Dhttp.maxConnections=100 -XX:NativeMemoryTracking=summary

再用jcmd看看nmt结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
Native Memory Tracking:

Total: reserved=771MB, committed=445MB
- Java Heap (reserved=250MB, committed=250MB)
(mmap: reserved=250MB, committed=250MB)

- Class (reserved=197MB, committed=76MB)
(classes #12379)
(malloc=11MB #21694)
(mmap: reserved=186MB, committed=65MB)

- Thread (reserved=21MB, committed=21MB)
(thread #40)
(stack: reserved=20MB, committed=20MB)

- Code (reserved=252MB, committed=47MB)
(malloc=8MB #10280)
(mmap: reserved=244MB, committed=39MB)

- GC (reserved=19MB, committed=19MB)
(malloc=10MB #252)
(mmap: reserved=9MB, committed=9MB)

- Internal (reserved=12MB, committed=12MB)
(malloc=12MB #14653)

- Symbol (reserved=16MB, committed=16MB)
(malloc=13MB #140934)
(arena=3MB #1)

- Native Memory Tracking (reserved=3MB, committed=3MB)
(tracking overhead=3MB)

class这块申请的内存变成197M了,这也不是我想要的结果。而且依然全局超了512M的限制。

看看oracle官方怎么说吧
https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/considerations.html