Quoting: Java SE 8 HotSpot[tm] Virtual Machine Garbage Collection Tuning
* Class metadata is deallocated when the corresponding Java class is unloaded.
* Java classes are unloaded as a results of garbage collection and garbage
* collections may be induced in order to unload classes and deallocate class
* metadata. When the space used for class metadata reaches a certain level
* (call it a high-water mark), a garbage collection is induced.
* After the garbage collection the high-water mark may be raised or lowered
* depending on the amount of space freed from class metadata. The high-water
* mark would be raised so as not to induce another garbage collection too soon.
* The high-water mark is initially set to the value of the command-line
* flag MetaspaceSize . It is raised or lowered based on the flags
* MaxMetaspaceFreeRatio and MinMetaspaceFreeRatio.
* If the committed space available for class metadata as a percentage of
* the total committed space for class metadata is greater than
* MaxMetaspaceFreeRatio, the high-water mark will be lowered.
* If it is less than MinMetaspaceFreeRatio, the high-water mark will be raised.
I check that Min/MaxMetaspaceFreeRatio settings could be used to lower
the high-water mark.
The test loads new classes (class by class) and monitor the amount of Used metaspace (via MXBean).
If the used amount become less, the GC has been induced. The test remember the moment of the first and
the second collections. If Min/MaxMetaspaceFreeRatio are set to 1 and 2, then according to the spec the second
GC should happen earlier. But this is not always true.
To reproduce the problem compile and run the GCDownTest.java:
# java -Xloggc:gc.log -XX:MaxMetaspaceFreeRatio=2 -XX:MinMetaspaceFreeRatio=1 \
-Xmx1G -XX:MetaspaceSize=20m -XX:MaxMetaspaceSize=30m GCDownTest
Example of output:
Starting...
The first GC!
Used: 11675600 --> 3225656
Committed: 20971520 --> 14680064
The second GC!
Used: 11689904 -- >3239800
Committed: 20971520 -- >14680064
Test failed: 11675600 less than 11689904
To make sure that GC was induced by metaspace:
# grep Full gc.log
9.216: [Full GC (Metadata GC Threshold) 12136K->1366K(90112K), 0.1884398 secs]
16.337: [Full GC (Metadata GC Threshold) 12950K->1429K(126976K), 0.1694265 secs]
The test passes on Linux-i586 and fail on Linux-x64, Solaris.
It's not very clear what does "the committed space available for class metadata as a
percentage of the total committed space for class metadata" mean, but I guess it should
be greater than 0.02 (MaxMetaspaceFreeRatio=2)
* Class metadata is deallocated when the corresponding Java class is unloaded.
* Java classes are unloaded as a results of garbage collection and garbage
* collections may be induced in order to unload classes and deallocate class
* metadata. When the space used for class metadata reaches a certain level
* (call it a high-water mark), a garbage collection is induced.
* After the garbage collection the high-water mark may be raised or lowered
* depending on the amount of space freed from class metadata. The high-water
* mark would be raised so as not to induce another garbage collection too soon.
* The high-water mark is initially set to the value of the command-line
* flag MetaspaceSize . It is raised or lowered based on the flags
* MaxMetaspaceFreeRatio and MinMetaspaceFreeRatio.
* If the committed space available for class metadata as a percentage of
* the total committed space for class metadata is greater than
* MaxMetaspaceFreeRatio, the high-water mark will be lowered.
* If it is less than MinMetaspaceFreeRatio, the high-water mark will be raised.
I check that Min/MaxMetaspaceFreeRatio settings could be used to lower
the high-water mark.
The test loads new classes (class by class) and monitor the amount of Used metaspace (via MXBean).
If the used amount become less, the GC has been induced. The test remember the moment of the first and
the second collections. If Min/MaxMetaspaceFreeRatio are set to 1 and 2, then according to the spec the second
GC should happen earlier. But this is not always true.
To reproduce the problem compile and run the GCDownTest.java:
# java -Xloggc:gc.log -XX:MaxMetaspaceFreeRatio=2 -XX:MinMetaspaceFreeRatio=1 \
-Xmx1G -XX:MetaspaceSize=20m -XX:MaxMetaspaceSize=30m GCDownTest
Example of output:
Starting...
The first GC!
Used: 11675600 --> 3225656
Committed: 20971520 --> 14680064
The second GC!
Used: 11689904 -- >3239800
Committed: 20971520 -- >14680064
Test failed: 11675600 less than 11689904
To make sure that GC was induced by metaspace:
# grep Full gc.log
9.216: [Full GC (Metadata GC Threshold) 12136K->1366K(90112K), 0.1884398 secs]
16.337: [Full GC (Metadata GC Threshold) 12950K->1429K(126976K), 0.1694265 secs]
The test passes on Linux-i586 and fail on Linux-x64, Solaris.
It's not very clear what does "the committed space available for class metadata as a
percentage of the total committed space for class metadata" mean, but I guess it should
be greater than 0.02 (MaxMetaspaceFreeRatio=2)