diff --git a/runtime/gc_base/modronapi.cpp b/runtime/gc_base/modronapi.cpp index cea86ceb17e..b201c446282 100644 --- a/runtime/gc_base/modronapi.cpp +++ b/runtime/gc_base/modronapi.cpp @@ -322,6 +322,10 @@ j9gc_is_managedpool_by_collector(J9JavaVM *javaVM, UDATA gcID, UDATA poolID) { MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(javaVM); if (extensions->_HeapManagementMXBeanBackCompatibilityEnabled) { + if (J9_GC_MANAGEMENT_COLLECTOR_SCAVENGE == gcID) { + /* for BackCompatible mode scavenge does not try to reclaim memory from the whole heap, so we do not mark JavaHeap managed by scavenge */ + return 0; + } return 1; } UDATA managedPools = 0; diff --git a/runtime/jcl/common/mgmtinit.c b/runtime/jcl/common/mgmtinit.c index ec964ab1516..4eb6ab29baa 100644 --- a/runtime/jcl/common/mgmtinit.c +++ b/runtime/jcl/common/mgmtinit.c @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 1998, 2017 IBM Corp. and others + * Copyright (c) 1998, 2018 IBM Corp. and others * * This program and the accompanying materials are made available under * the terms of the Eclipse Public License 2.0 which accompanies this @@ -479,6 +479,7 @@ gcStartEvent(J9JavaVM *vm, UDATA heapSize, UDATA heapUsed, UDATA *totals, UDATA J9MemoryPoolData *memoryPools = mgmt->memoryPools; J9MemoryNotification *notification = NULL; J9MemoryNotification *last = NULL; + J9GarbageCollectionInfo* gcInfo = NULL; UDATA total = 0; UDATA used = 0; @@ -500,21 +501,26 @@ gcStartEvent(J9JavaVM *vm, UDATA heapSize, UDATA heapUsed, UDATA *totals, UDATA mgmt->preCollectionHeapSize = heapSize; mgmt->preCollectionHeapUsed = heapUsed; + gcInfo = &gcData->lastGcInfo; for (idx = 0; idx < mgmt->supportedMemoryPools; ++idx) { J9MemoryPoolData *memoryPool = &memoryPools[idx]; total = totals[idx]; used = totals[idx] - frees[idx]; - memoryPool->preCollectionSize = total; - memoryPool->preCollectionUsed = used; - memoryPool->preCollectionMaxSize = memoryPool->postCollectionMaxSize; + /* update pre Memory Usage of last GcInfo for the collector */ + gcInfo->preUsed[idx] = used; + gcInfo->preCommitted[idx] = total; + if (0 == gcInfo->postMax[idx]) { + gcInfo->postMax[idx] = memoryPool->postCollectionMaxSize; + } + gcInfo->preMax[idx] = gcInfo->postMax[idx]; /* check the peak usage and update */ if (memoryPool->peakUsed < used) { memoryPool->peakUsed = used; memoryPool->peakSize = total; - memoryPool->peakMax = memoryPool->preCollectionMaxSize; + memoryPool->peakMax = gcInfo->preMax[idx]; } /* if a heap usage threshold is set, check whether we are above or below */ @@ -546,7 +552,7 @@ gcStartEvent(J9JavaVM *vm, UDATA heapSize, UDATA heapUsed, UDATA *totals, UDATA notification->usageThreshold->poolID = memoryPool->id; notification->usageThreshold->usedSize = used; notification->usageThreshold->totalSize = total; - notification->usageThreshold->maxSize = memoryPool->preCollectionMaxSize; + notification->usageThreshold->maxSize = gcInfo->preMax[idx]; notification->usageThreshold->thresholdCrossingCount = memoryPool->usageThresholdCrossedCount; notification->sequenceNumber = mgmt->notificationCount++; @@ -601,6 +607,7 @@ gcEndEvent(J9JavaVM *vm, UDATA heapSize, UDATA heapUsed, UDATA *totals, UDATA *f UDATA total = 0; UDATA used = 0; + UDATA max = 0; UDATA idx = 0; U_32 notificationEnabled = 0; @@ -613,27 +620,31 @@ gcEndEvent(J9JavaVM *vm, UDATA heapSize, UDATA heapUsed, UDATA *totals, UDATA *f /* lock the management struct */ omrthread_rwmutex_enter_write(mgmt->managementDataLock); + mgmt->lastGCID = (U_32)collectorID; mgmt->postCollectionHeapSize = heapSize; mgmt->postCollectionHeapUsed = heapUsed; + gcInfo = &gcData->lastGcInfo; for (idx = 0; idx < mgmt->supportedMemoryPools; ++idx) { J9MemoryPoolData *memoryPool = &memoryPools[idx]; total = totals[idx]; used = totals[idx] - frees[idx]; + max = maxs[idx]; - memoryPool->postCollectionSize = total; - memoryPool->postCollectionUsed = used; - memoryPool->postCollectionMaxSize = maxs[idx]; + /* update post Memory Usage of last GcInfo for the collector */ + gcInfo->postUsed[idx] = used; + gcInfo->postCommitted[idx] = total; + gcInfo->postMax[idx] = max; /* check the peak usage and update */ if (memoryPool->peakUsed < used) { memoryPool->peakUsed = used; memoryPool->peakSize = total; - memoryPool->peakMax = memoryPool->postCollectionMaxSize; + memoryPool->peakMax = max; } - /* if a heap collection threshold is set, check whether we are above or below */ - if (0 < memoryPool->collectionUsageThreshold) { + /* if a memory pool collection threshold is set and the memory pool is managed by the collector, check whether we are above or below */ + if ((0 < memoryPool->collectionUsageThreshold) && mmFuncs->j9gc_is_managedpool_by_collector(vm, (UDATA)(gcData->id & J9VM_MANAGEMENT_GC_HEAP_ID_MASK), (UDATA)(memoryPool->id & J9VM_MANAGEMENT_POOL_HEAP_ID_MASK))) { if (memoryPool->collectionUsageThreshold < used) { /* usage above threshold now, was it below threshold last time? */ if (0 == (memoryPool->notificationState & COLLECTION_THRESHOLD_EXCEEDED)) { @@ -661,7 +672,7 @@ gcEndEvent(J9JavaVM *vm, UDATA heapSize, UDATA heapUsed, UDATA *totals, UDATA *f notification->usageThreshold->poolID = memoryPool->id; notification->usageThreshold->usedSize = used; notification->usageThreshold->totalSize = total; - notification->usageThreshold->maxSize = memoryPool->postCollectionMaxSize; + notification->usageThreshold->maxSize = max; notification->usageThreshold->thresholdCrossingCount = memoryPool->collectionUsageThresholdCrossedCount; notification->sequenceNumber = mgmt->notificationCount++; @@ -731,7 +742,6 @@ gcEndEvent(J9JavaVM *vm, UDATA heapSize, UDATA heapUsed, UDATA *totals, UDATA *f /* update nonHeap memory pools for postCollection */ updateNonHeapMemoryPoolSizes(vm, mgmt, TRUE); /* update J9GarbageCollectionInfo for the collector */ - gcInfo = &gcData->lastGcInfo; gcInfo->gcID = gcData->id; gcInfo->gcAction = mmFuncs->j9gc_get_gc_action(vm, (gcInfo->gcID & J9VM_MANAGEMENT_GC_HEAP_ID_MASK)); @@ -741,12 +751,19 @@ gcEndEvent(J9JavaVM *vm, UDATA heapSize, UDATA heapUsed, UDATA *totals, UDATA *f for (idx = 0; supportedMemoryPools > idx; ++idx) { J9MemoryPoolData *memoryPool = &memoryPools[idx]; gcInfo->initialSize[idx] = memoryPool->initialSize; - gcInfo->preUsed[idx] = memoryPool->preCollectionUsed; - gcInfo->preCommitted[idx] = memoryPool->preCollectionSize; - gcInfo->preMax[idx] = (I_64) memoryPool->preCollectionMaxSize; - gcInfo->postUsed[idx] = memoryPool->postCollectionUsed; - gcInfo->postCommitted[idx] = memoryPool->postCollectionSize; - gcInfo->postMax[idx] = (I_64) memoryPool->postCollectionMaxSize; + if (mmFuncs->j9gc_is_managedpool_by_collector(vm, (UDATA)(gcData->id & J9VM_MANAGEMENT_GC_HEAP_ID_MASK), (UDATA)(memoryPool->id & J9VM_MANAGEMENT_POOL_HEAP_ID_MASK))) { + /** + * the memoryPool is managed by this collection, update preCollection postCollection Memory Usage of this memory Pool + * gcInfo keep memory Usage before and after this gc + * preCollection postCollection Memory Usage in memoryPool only keep information for the GC, which recycle the memory pool + */ + memoryPool->preCollectionUsed = gcInfo->preUsed[idx]; + memoryPool->preCollectionSize = gcInfo->preCommitted[idx]; + memoryPool->preCollectionMaxSize = (U_64)gcInfo->preMax[idx]; + memoryPool->postCollectionUsed = gcInfo->postUsed[idx]; + memoryPool->postCollectionSize = gcInfo->postCommitted[idx]; + memoryPool->postCollectionMaxSize = (U_64)gcInfo->postMax[idx]; + } } /* non heap memory pools */ for (; supportedMemoryPools + supportedNonHeapMemoryPools > idx; ++idx) { diff --git a/runtime/jcl/common/mgmtmempool.c b/runtime/jcl/common/mgmtmempool.c index 019fb64d9d8..1ee7858bd1d 100644 --- a/runtime/jcl/common/mgmtmempool.c +++ b/runtime/jcl/common/mgmtmempool.c @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 1998, 2016 IBM Corp. and others + * Copyright (c) 1998, 2018 IBM Corp. and others * * This program and the accompanying materials are made available under * the terms of the Eclipse Public License 2.0 which accompanies this @@ -27,6 +27,7 @@ static jobject processSegmentList(JNIEnv *env, jclass memoryUsage, jobject memUsageConstructor, J9MemorySegmentList *segList, U_64 initSize, U_64 *storedPeakSize, U_64 *storedPeakUsed, UDATA action); static UDATA getIndexFromPoolID(J9JavaLangManagementData *mgmt, UDATA id); +static UDATA getIndexFromCollectorID(J9JavaLangManagementData *mgmt, UDATA id); static J9MemorySegmentList *getMemorySegmentList(J9JavaVM *javaVM, jint id); jobject JNICALL @@ -129,7 +130,13 @@ Java_com_ibm_java_lang_management_internal_MemoryPoolMXBeanImpl_getPeakUsageImpl if (currentUsed > pool->peakUsed) { pool->peakUsed = currentUsed; pool->peakSize = currentCommitted; - pool->peakMax = pool->postCollectionMaxSize; + if (0 != mgmt->lastGCID) { + J9GarbageCollectorData *gcData = &mgmt->garbageCollectors[getIndexFromCollectorID(mgmt, mgmt->lastGCID)]; + J9GarbageCollectionInfo* gcInfo = &gcData->lastGcInfo; + pool->peakMax = gcInfo->postMax[idx]; + } else { + pool->peakMax = pool->postCollectionMaxSize; + } used = currentUsed; committed = currentCommitted; max = pool->peakMax; @@ -180,7 +187,14 @@ Java_com_ibm_java_lang_management_internal_MemoryPoolMXBeanImpl_getUsageImpl(JNI omrthread_rwmutex_enter_read(mgmt->managementDataLock); peak = (jlong) pool->peakUsed; init = (jlong) pool->initialSize; - max = (jlong) pool->postCollectionMaxSize; + if (0 != mgmt->lastGCID) { + J9GarbageCollectorData *gcData = &mgmt->garbageCollectors[getIndexFromCollectorID(mgmt, mgmt->lastGCID)]; + J9GarbageCollectionInfo* gcInfo = &gcData->lastGcInfo; + max = (jlong) gcInfo->postMax[idx]; + } else { + max = (jlong) pool->postCollectionMaxSize; + } + omrthread_rwmutex_exit_read(mgmt->managementDataLock); if (used > peak) { @@ -189,7 +203,7 @@ Java_com_ibm_java_lang_management_internal_MemoryPoolMXBeanImpl_getUsageImpl(JNI if ((U_64)used > pool->peakUsed) { pool->peakUsed = used; pool->peakSize = committed; - pool->peakMax = pool->postCollectionMaxSize; + pool->peakMax = max; } omrthread_rwmutex_exit_write(mgmt->managementDataLock); } @@ -352,7 +366,13 @@ Java_com_ibm_java_lang_management_internal_MemoryPoolMXBeanImpl_resetPeakUsageIm omrthread_rwmutex_enter_write(mgmt->managementDataLock); pool->peakUsed = used; pool->peakSize = committed; - pool->peakMax = pool->postCollectionMaxSize; + if (0 != mgmt->lastGCID) { + J9GarbageCollectorData *gcData = &mgmt->garbageCollectors[getIndexFromCollectorID(mgmt, mgmt->lastGCID)]; + J9GarbageCollectionInfo* gcInfo = &gcData->lastGcInfo; + pool->peakMax = gcInfo->postMax[idx]; + } else { + pool->peakMax = pool->postCollectionMaxSize; + } omrthread_rwmutex_exit_write(mgmt->managementDataLock); } else { /* NonHeap MemoryPool */ @@ -496,7 +516,7 @@ static UDATA getIndexFromPoolID(J9JavaLangManagementData *mgmt, UDATA id) { UDATA idx = 0; - for(; idx < mgmt->supportedMemoryPools; idx++) { + for (idx = 0; idx < mgmt->supportedMemoryPools; idx++) { if ((mgmt->memoryPools[idx].id & J9VM_MANAGEMENT_POOL_HEAP_ID_MASK) == (id & J9VM_MANAGEMENT_POOL_HEAP_ID_MASK)) { break; } @@ -504,6 +524,18 @@ getIndexFromPoolID(J9JavaLangManagementData *mgmt, UDATA id) return idx; } +static UDATA +getIndexFromCollectorID(J9JavaLangManagementData *mgmt, UDATA id) +{ + UDATA idx = 0; + for (idx = 0; idx < mgmt->supportedCollectors; ++idx) { + if ((J9VM_MANAGEMENT_GC_HEAP_ID_MASK & mgmt->garbageCollectors[idx].id) == (J9VM_MANAGEMENT_GC_HEAP_ID_MASK & id)) { + break; + } + } + return idx; +} + static J9MemorySegmentList * getMemorySegmentList(J9JavaVM *javaVM, jint id) { diff --git a/runtime/oti/j9nonbuilder.h b/runtime/oti/j9nonbuilder.h index 92912792172..c141c0a0fa1 100644 --- a/runtime/oti/j9nonbuilder.h +++ b/runtime/oti/j9nonbuilder.h @@ -921,6 +921,7 @@ typedef struct J9JavaLangManagementData { U_32 supportedMemoryPools; U_32 supportedNonHeapMemoryPools; U_32 supportedCollectors; + U_32 lastGCID; struct J9MemoryPoolData *memoryPools; struct J9NonHeapMemoryData *nonHeapMemoryPools; struct J9GarbageCollectorData *garbageCollectors;