最近开始优化线上整个微服务的内存使用了。本来是通过抓取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