For the java followers, which have been seeing the java language evolve the last couple of years remember the big difference between JDK 7 vs JDK 8 when the metaspace was “created” as in perm gen was removed from heap. And this change made much sense, in the sense that loading information from the classes are set to be outside of the heap. Basically we have on JDK 8+ class metadata are allocated when classes are loaded in native.
However, the main impact we have seen in some scenarios, was when applications with high number class loading occupy a considerable (as in non trivial) amount of space on the memory, but now on the native side. And it was like that for quite awhile, the technical reason is that you have each class loader taking a part of the metachunks and occupying a space on its arena – the more class loaders, the more space it takes – i.e. per-class loader areas. This space would only grow with time, the more class loaders and classes are loaded.
That’s not the case anymore, and now with Elastic Metaspace, which basically introduces mechanisms of uncommitting the memory back to the OS – and commit memory only on demand (seriously, before it was just a big commited space without usage), i.e. allocator will attempt to return memory to the OS after class unloading, in a much more eagerly than it did before Elastic Metaspace, which is implemented via the Buddy Memory allocation algorithm.
And of course, more JVM options in Java means usually mean new flags, and that’s why the new JVM flag MetaspaceReclaimStrategy was introduced the flag has three options: none, balanced, and aggressive, as described on JDK-8242841. Balanced is the default.
Balanced | shall enable a reasonable compromise between reclaiming memory and the incurred costs. The majority of applications should see improved memory usage after class unloading while not noticing added costs. In particular, the number of virtual memory areas should only marginally increase. This setting aims to deliver backward compatible behavior while still giving the benefit of reduced memory usage. |
Aggressive | shall enable more aggressive memory reclamation at possibly increased cost. Choosing this setting means the user would be willing to increase the OS specific limit on virtual memory areas if needed. However, “aggressive” should still be a perfectly viable setting. |
none | disable memory reclamation |
Tradeoff
The consequence of the previous implementation – reserve/commit a big chunk even when not used – is that you can use more than needed and reclaiming is not an option, aka non Elastic Metaspace. If you would would like to make it this way, just set MetaspaceReclaimStrategy=none.
The new implementation, i.e. Elastic Metaspace, the tradeoff will be:
1. Losing cpu cycles in the uncommitting process ~ meaning CPU overhead.
2. uncomitting memory may increase the number of virtual memory areas (memory mappings) ~ meaning (virtual) memory overhead. Use `ulimit -v
` to see the current limit. From what I searched the virtual limit would be 2^48 for 64 bits ~ still learning about it though.
Complete description of the algorithm here and overview on the JEP 387