8219524: Shenandoah misreports "committed" size in MemoryMXBean
Reviewed-by: rkennke, zgu
--- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp Thu Feb 21 14:16:44 2019 +0100
+++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp Thu Feb 21 15:52:42 2019 +0100
@@ -2639,6 +2639,10 @@
return memory_pools;
}
+MemoryUsage ShenandoahHeap::memory_usage() {
+ return _memory_pool->get_memory_usage();
+}
+
void ShenandoahHeap::enter_evacuation() {
_oom_evac_handler.enter_evacuation();
}
--- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp Thu Feb 21 14:16:44 2019 +0100
+++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp Thu Feb 21 15:52:42 2019 +0100
@@ -511,6 +511,7 @@
GrowableArray<GCMemoryManager*> memory_managers();
GrowableArray<MemoryPool*> memory_pools();
+ MemoryUsage memory_usage();
GCTracer* tracer();
GCTimer* gc_timer() const;
CollectorPolicy* collector_policy() const;
--- a/src/hotspot/share/gc/shenandoah/shenandoahMemoryPool.cpp Thu Feb 21 14:16:44 2019 +0100
+++ b/src/hotspot/share/gc/shenandoah/shenandoahMemoryPool.cpp Thu Feb 21 15:52:42 2019 +0100
@@ -26,7 +26,7 @@
ShenandoahMemoryPool::ShenandoahMemoryPool(ShenandoahHeap* heap) :
CollectedMemoryPool("Shenandoah",
- heap->capacity(),
+ heap->initial_capacity(),
heap->max_capacity(),
true /* support_usage_threshold */),
_heap(heap) {}
@@ -37,9 +37,15 @@
size_t used = used_in_bytes();
size_t committed = _heap->committed();
+ // These asserts can never fail: max is stable, and all updates to other values never overflow max.
assert(initial <= max, "initial: " SIZE_FORMAT ", max: " SIZE_FORMAT, initial, max);
assert(used <= max, "used: " SIZE_FORMAT ", max: " SIZE_FORMAT, used, max);
assert(committed <= max, "committed: " SIZE_FORMAT ", max: " SIZE_FORMAT, committed, max);
+
+ // Committed and used are updated concurrently and independently. They can momentarily break
+ // the assert below, which would also fail in downstream code. To avoid that, adjust values
+ // to make sense under the race. See JDK-8207200.
+ committed = MAX2(used, committed);
assert(used <= committed, "used: " SIZE_FORMAT ", committed: " SIZE_FORMAT, used, committed);
return MemoryUsage(initial, used, committed, max);
--- a/test/hotspot/jtreg/gc/shenandoah/mxbeans/TestMemoryMXBeans.java Thu Feb 21 14:16:44 2019 +0100
+++ b/test/hotspot/jtreg/gc/shenandoah/mxbeans/TestMemoryMXBeans.java Thu Feb 21 15:52:42 2019 +0100
@@ -52,8 +52,10 @@
public static void testMemoryBean(long initSize, long maxSize) {
MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
long heapInit = memoryMXBean.getHeapMemoryUsage().getInit();
+ long heapCommitted = memoryMXBean.getHeapMemoryUsage().getCommitted();
long heapMax = memoryMXBean.getHeapMemoryUsage().getMax();
long nonHeapInit = memoryMXBean.getNonHeapMemoryUsage().getInit();
+ long nonHeapCommitted = memoryMXBean.getNonHeapMemoryUsage().getCommitted();
long nonHeapMax = memoryMXBean.getNonHeapMemoryUsage().getMax();
if (initSize > 0 && heapInit != initSize) {
@@ -62,5 +64,9 @@
if (maxSize > 0 && heapMax != maxSize) {
throw new IllegalStateException("Max heap size is wrong: " + heapMax + " vs " + maxSize);
}
+ if (initSize > 0 && maxSize > 0 && initSize != maxSize && heapCommitted == heapMax) {
+ throw new IllegalStateException("Init committed heap size is wrong: " + heapCommitted +
+ " (init: " + initSize + ", max: " + maxSize + ")");
+ }
}
}