Thursday, August 14, 2014

HotSpot: Understanding Metaspace in JDK 8

In JDK 8, it will print out the following information when JVM exits:
Heap
 <snipped> 
 Metaspace       used 2425K, capacity 4498K, committed 4864K, reserved 1056768K
  class space    used 262K, capacity 386K, committed 512K, reserved 1048576K
if you have enabled GC printing using:
-XX:+PrintGCDetails -XX:+PrintGCTimeStamps
Note that if PrintGCDetails is enabled, PrintGC[1] is also enabled.

In this article, we will examine what the above lines mean.

Metaspace


Internal JVM memory management is, to a large extent, kept off the Java heap and allocated natively in the operating system, through system calls like malloc or mmap. This non-heap system memory allocated by the JVM is referred to as native memory. Similar to the Oracle JRockit and IBM JVM's, the JDK 8 HotSpot JVM is now using native memory for the representation of class metadata, which is called Metaspace.[2,4]

In JDK 8, Hotspot explicitly manages the space used for metadata. Space is requested from the OS and then divided into chunks. A class loader will allocate space for metadata from its chunks (a chunk is to bound to a specific class loader). When classes are unloaded for a class loader, its chunks are recycled for reuse or returned to the OS.   Note that metadata uses mmap'ed space and not malloc'ed space.

Used/Capacity/Committed/Reserved


When JVM exits, it prints the following information if you have enabled GC printing:
 Metaspace       used 2425K, capacity 4498K, committed 4864K, reserved 1056768K
  class space    used 262K, capacity 386K, committed 512K, reserved 1048576K
In the “Metaspace” line, the “used” is the amount of space used for loaded classes and other metadata. The “capacity” is the space available for metadata in currently allocated chunks. The “committed” value is the amount of space available for chunks. The “reserved” is the amount of space reserved (but not necessarily committed) for metadata. On the “class space” line, those values are the corresponding values for the class area in Metaspace when compressed class pointers are used.

Mataspace is dynamically managed by HotSpot.  Metadata are deallocated when their class loader are garbage collected (GC'ed).  A high water mark is used for inducing a GC—when committed memory of all metaspaces reaches this level, a GC is triggered.  You can use the following flag:
-XX:MetaspaceSize=<size>
to specify the initial high water level. 

The interaction between metaspace growth and GC can be summarized as follows:
Metaspaces expand the native memory it is using until it gets to some level (starts at MetaspaceSize). When it hits that level, it does a GC to see if classes can be unloaded. After the GC, it can use freed space in it for metadata. If not enough space has been freed, it uses more native memory.
After the GC it also decides what the next level is for doing a GC to unload classes.  The level mostly increases to have fewer GC's. It sometimes will decrease if lots of space has been freed due to class unloading.  If MetaspaceSize is set higher, then fewer GC will be done early.

Acknowledgement


Some writings here are based on the feedback from Jon Masamitsu. However, the author would assume the full responsibility for the content himself.

References

    1. Java HotSpot VM Options
    2. HotSpot: Monitoring and Tuning Metaspace in JDK 8
    3. Latest JDK 8 and JDK 7 available here
    4. JavaOne Wednesday: Permanent Generation Removal Overview   
    5. jstat Tool: New Metaspace Statistics from -gc Option 
    6. Metatspace in JDK 8 (good) 
    7. VM Class Loading
    8. Learn More About Performance Improvements in JDK 8 

    No comments: