Understanding metaspace line in JVM heap printout
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
- Look for an existing free chunk in the free list.
- If there is no suitable free chunk, allocate a new one from the current Virtual Space.
- 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.
In jdk 1.8+, how metaspace layout the class info?
First of all, things like Metaspace and String Table are not specified in JLS or JVMS. It's exclusively an internal implementation detail of the particular JVM. For example, there are fully compliant JVM implementations that do not have Metaspace at all.
If we talk about the modern HotSpot JVM, your understanding is not quite correct.
- No. An instance of
java.lang.String
object representing"a"
is in Java Heap. The string table contains a reference to that object as long as"a"
is strongly reachable. - Yes.
- No. Run-Time Constant Pool holds things described in JVMS §4.4. Static fields belong to a class mirror, which is an instance of
java.lang.Class
in Java Heap. - The same as 1.
- Metaspace (as the "meta" prefix suggests) contains the class metadata, but not the data itself. E.g. the metaspace includes the information that the class
MetaspaceTest
has a field namedliteralStr
of typejava.lang.String
, but it has nothing to do with the value of that field. - Yes.
- No. As written above, Metaspace contains only the description of fields, but not the data. The actual holder of instance fields is an object instance; the actual holder of static fields is a class mirror, i.e. the instance of
java.lang.Class
in the heap.
Does JVM metaspace always trigger GC when resizing
First of all, "the size of the metaspace" is ambiguous, and thus meaningless without the context. There are at least five metrics: reserved, committed, capacity and used memory as described in this answer, and the high-water mark, also known as capacity_until_gc.
Metaspace is not just one contiguous region of memory, so it does not resize in the common sense. Instead, when allocation happens, one or more of the above metrics changes.
- On the fastest path a block of metadata is allocated from the current chunk.
used
memory increases in this case, and that's it. - If there is not enough room in the current chunk, JVM searches for a possibly free existing chunk. If it succeeds in reusing chunks,
capacity
increases. No GC happens until this point. - If there are no free chunks, JVM tries to commit more memory, unless the new
committed
size would exceedcapacity_until_gc
. - If
capacity_until_gc
threshold is reached, JVM triggers a GC cycle. - If GC does not free enough memory, the high-water mark is increased so that another Virtual Space will be allocated.
After GC, the high-water mark value is adjusted basing on the following JVM flags:
-XX:MinMetaspaceFreeRatio
(used to calculate how much free space is desirable in the metaspace capacity to decide how much to increase the HWM);-XX:MaxMetaspaceFreeRatio
(used to decide how much free space is desirable in the metaspace capacity before decreasing the HWM);-XX:MinMetaspaceExpansion
(the minimum expansion of Metaspace in bytes);-XX:MaxMetaspaceExpansion
(the maximum expansion of Metaspace without full GC).
TL;DR It's not that simple. JVM can definitely commit more Metaspace memory without triggering GC. However, when HWM is reached, GC is triggered and HWM is recomputed according to the ergonomics policy.
Metaspace utilization of JVM
It shows the current Metaspace occupancy relative to the current Metaspace capacity, i.e.
used / capacity
Metaspace used
, capacity
, committed
and reserved
values are illustrated in this answer.
This is a rather useless metrics since Metaspace can grow and shrink during an application lifecycle.
jstat and jcmd giving different answers for metaspace memory
Good catch! The numbers are indeed different: jstat values can slightly fall behind, since they are updated only after GC, while jcmd values are always current.
So, jcmd GC.heap_info
should be more accurate.
Also note that MC
in jstat output corresponds to the metaspace committed size, not the capacity.
Metaspace allocated more then MaxMetaspaceSize
The answer is basically here, though not trivial to understand.
The MaxMetaspaceSize
limits the committed memory, while your GC logs actually print the reserved memory. So reserved: 1058816K
, committed: 9975K
, according to your log. Reserved memory does not have to be backed by swap or actual RAM, at all, so usually it is very big.
That is why you see those big numbers in the GC log
.
Related Topics
What's Java Hybrid - Applet + Application
Java: How to Get Input from System.Console()
Replacing a Fragment with Another Fragment Inside Activity Group
Change the System Brightness Programmatically
How to Change Menu Item Text Dynamically in Android
Android Load from Url to Bitmap
How to Kill a Linux Process in Java with Sigkill Process.Destroy() Does Sigterm
Java Animation Programs Running Jerky in Linux
Wireless API for Linux in C or Java
How Does Linux Recognize a File as a Certain File Type, and How to Programmatically Change It
Multiple Row Selection in Jtable
Firestore - Merging Two Queries Locally
How to Add a Textview to Linearlayout in Android
Sqlite in Android How to Update a Specific Row
Listview Onitemclicklistener Not Responding
Could Not Reserve Enough Space for Object Heap to Start Jvm
File.Encoding Has No Effect, Lc_All Environment Variable Does It