1
votes

The initial problem is that java application is docker was OOM-killed due to memory usage. So I started to use NMT to understand why the consumption is more then expected. JVM version is 1.8.0_212 with container support. docker is launched with next java options

JAVA_OPTS='-XX:+AlwaysPreTouch -Xmx128m -Xms128m -XX:MaxMetaspaceSize=150m -XX:ReservedCodeCacheSize=100m -XX:+UseStringDeduplication -XX:+PrintFlagsFinal -XshowSettings:vm -XX:NativeMemoryTracking=detail' ... -m="450m" --cpu-shares="256" docker-image

Native Memory Tracking:

Total: reserved=1464054KB +843KB, committed=344578KB +1359KB

...

-                     Class (reserved=1124594KB +19KB, committed=85066KB +275KB)
                            (classes #15631)
                            (malloc=2290KB +19KB #20081 +27)
                            (mmap: reserved=1122304KB, committed=82776KB +256KB)
...

All numbers are as expected. The only question is for Class field, as it shows reserved value of ~ 1GB, can it be somehow decreased?

1
Why? Your problem is to provide enough memory, not to decrease anything. - user207421
You really use 15691 classes, they are just there. - atline
1gd reserved, seems too much for my small microservice, which is doing nothing :) it seems that because of some logic (possibly because of aop-spring) it generates new classes constantly. And because the limit is 1gb, it will newer GC - user2105282
You can see the biggest change by changing default GC algorithm(Parallel GC) with -XX:+UseSerialGC parameter. - Turac

1 Answers

4
votes

This is Compressed Class Space.

The default limit is exactly 1GB, it can be decreased with -XX:CompressedClassSpaceSize=N.

The "Class" area in Native Memory Tracking output includes both Metaspace and Compressed Class Space, that's why you see more than 1GB reserved. However, the reserved memory is just the amount of virtual address space - it does not take physical memory pages.

More about JVM virtual memory