Understanding metaspace line in JVM heap printout

In a Java 8 heap printout, you may see a line that looks like:

Metaspace used 2425K, capacity 4498K, committed 4864K, reserved 1056768K

https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/considerations.html tries to explain the line:

In the line beginning with Metaspace, the used value is the amount of space used for loaded classes. The capacity value is the space available for metadata in currently allocated chunks. The committed value is the amount of space available for chunks. The reserved value is the amount of space reserved (but not necessarily committed) for metadata.

Again, from the above link:

Space is requested from the OS and then divided into chunks. A class loader allocates space for metadata from its chunks (a chunk is bound to a specific class loader).

I want to know what each field means (used, capacity, committed, reserved), but I am struggling to understand the above definitions.

My understanding is that metaspace is carved out of the JVM process's virtual address space. The JVM reserves an initial size on startup based on -XX:MetaspaceSize, which has an undocumented, platform-specific default. I assume that reserved refers to the total size of the metaspace. The space is divided into chunks. I am not sure if each chunk has the same size. Each chunk contains class metadata associated with a single class loader.

Capacity and committed sounds like free space to me (based on the definitions from the link). Since metadata is stored within chunks, then I would assume that used + capacity would equal committed, but it doesn't. Maybe committed means reserved space that is used, but then what would used mean? Used space used by metadata? Then, what other ways are there to use the space?

I hope you see my confusion. I would appreciate clarification on the definitions.


Solution 1:

Metaspace layout

Metaspace consists of one or more Virtual Spaces. Virtual Spaces are areas of contiguous address space obtained from the OS. They are allocated on demand. When allocated, Virtual Space reserves memory from the OS, but not yet commits it. Metaspace reserved memory is the total size of all Virtual Spaces.

Allocation unit inside Virtual Space is Metachunk (or simply Chunk). When a new chunk is allocated from a Virtual Space, the corresponding memory is committed. Metaspace committed memory is the total size of all chunks.

Chunks may differ in size. When a ClassLoader gets garbage collected, all Metachunks belonging to it are freed. Free chunks are maintained in the global free list. Metaspace capacity is the total size of all allocated (i.e. not free) chunks.

New chunk allocation

  1. Look for an existing free chunk in the free list.
  2. If there is no suitable free chunk, allocate a new one from the current Virtual Space.
  3. If the current Virtual Space is exhausted, reserve a new Virtual Space.

Class metadata is allocated within a chunk. Chunk may not contain data from multiple ClassLoaders, but one ClassLoader may have several chunks. Metaspace used is the total size of all class metadata from all chunks.