Skip to content

Commit

Permalink
gc notifications
Browse files Browse the repository at this point in the history
  • Loading branch information
roberttoyonaga committed Oct 1, 2024
1 parent a8efbf7 commit 1b5236a
Show file tree
Hide file tree
Showing 21 changed files with 1,005 additions and 70 deletions.
6 changes: 6 additions & 0 deletions substratevm/mx.substratevm/suite.py
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,9 @@
"java.management": [
"sun.management",
],
"jdk.management": [
"com.sun.management.internal"
],
"jdk.internal.vm.ci" : [
"jdk.vm.ci.code",
],
Expand Down Expand Up @@ -994,6 +997,9 @@
"jdk.internal.misc",
"sun.security.jca",
],
"java.management": [
"sun.management",
],
},
"checkstyle": "com.oracle.svm.test",
"checkstyleVersion" : "10.7.0",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
/*
* Copyright (c) 2024, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2024, 2024, Red Hat Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.oracle.svm.core.genscavenge;

import com.oracle.svm.core.util.BasedOnJDKFile;

import com.oracle.svm.core.SubstrateUtil;
import com.oracle.svm.core.genscavenge.service.GcNotificationRequest;
import com.oracle.svm.core.genscavenge.service.PoolMemoryUsage;
import com.oracle.svm.core.genscavenge.service.Target_com_sun_management_GcInfo;
import com.oracle.svm.core.genscavenge.service.Target_java_lang_management_internal_GcInfoBuilder;

import com.sun.management.GarbageCollectionNotificationInfo;
import com.sun.management.GcInfo;
import com.sun.management.internal.GarbageCollectionNotifInfoCompositeData;
import com.sun.management.internal.GcInfoBuilder;
import sun.management.NotificationEmitterSupport;

import javax.management.MBeanNotificationInfo;
import javax.management.Notification;
import javax.management.NotificationEmitter;
import javax.management.openmbean.CompositeData;
import java.lang.management.MemoryUsage;

public abstract class AbstractGarbageCollectorMXBean extends NotificationEmitterSupport
implements com.sun.management.GarbageCollectorMXBean, NotificationEmitter {
@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-24+14/src/hotspot/share/gc/serial/serialHeap.cpp#L451") //

private static final String ACTION_MINOR = "end of minor GC";
@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-24+14/src/hotspot/share/gc/serial/serialHeap.cpp#L718") //
private static final String ACTION_MAJOR = "end of major GC";
private GcInfoBuilder gcInfoBuilder;
private volatile GcInfo gcInfo;
private long seqNumber = 0;

private synchronized GcInfoBuilder getGcInfoBuilder() {
if (gcInfoBuilder == null) {
Target_java_lang_management_internal_GcInfoBuilder gib = new Target_java_lang_management_internal_GcInfoBuilder(this, getMemoryPoolNames());
gcInfoBuilder = SubstrateUtil.cast(gib, GcInfoBuilder.class);
}
return gcInfoBuilder;
}

/**
* Use the data taken from the request queue to populate MemoryUsage. The service thread calls
* this method.
*/
public void createNotification(GcNotificationRequest request) {
AbstractMemoryPoolMXBean[] beans = GenScavengeMemoryPoolMXBeans.singleton().getMXBeans();

String[] poolNames = getMemoryPoolNames();
MemoryUsage[] before = new MemoryUsage[poolNames.length];
MemoryUsage[] after = new MemoryUsage[poolNames.length];

// Pools must be in the order of getMemoryPoolNames() to match GcInfoBuilder
for (int i = 0; i < poolNames.length; i++) {
for (int j = 0; j < beans.length; j++) {
PoolMemoryUsage pmu = request.getPoolBefore(j);
if (pmu.name != null && pmu.name.equals(poolNames[i])) {
before[i] = beans[j].memoryUsage(pmu.used, pmu.committed);
pmu = request.getPoolAfter(j);
after[i] = beans[j].memoryUsage(pmu.used, pmu.committed);
}
}
}

// Number of GC threads.
Object[] extAttribute = new Object[]{Integer.valueOf(1)};

Target_com_sun_management_GcInfo targetGcInfo = new Target_com_sun_management_GcInfo(getGcInfoBuilder(), request.epoch, request.startTime, request.endTime, before, after, extAttribute);
gcInfo = SubstrateUtil.cast(targetGcInfo, GcInfo.class);

GarbageCollectionNotificationInfo info = new GarbageCollectionNotificationInfo(
getName(),
request.isIncremental ? ACTION_MINOR : ACTION_MAJOR,
request.cause.getName(),
gcInfo);

CompositeData cd = GarbageCollectionNotifInfoCompositeData.toCompositeData(info);

Notification notif = new Notification(GarbageCollectionNotificationInfo.GARBAGE_COLLECTION_NOTIFICATION,
getObjectName(),
getNextSeqNumber(),
request.timestamp,
getName());
notif.setUserData(cd);

sendNotification(notif);
}

private long getNextSeqNumber() {
return ++seqNumber;
}

@Override
public MBeanNotificationInfo[] getNotificationInfo() {
return new MBeanNotificationInfo[]{
new MBeanNotificationInfo(
new String[]{GarbageCollectionNotificationInfo.GARBAGE_COLLECTION_NOTIFICATION},
"javax.management.Notification",
"GC Notification")
};
}

/** OpenJDK calls to native code to obtain this. */
@Override
public GcInfo getLastGcInfo() {
return gcInfo;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,12 @@ UnsignedWord getInitialValue() {
return initialValue;
}

public abstract long getUsedBytes();

public long getCommittedBytes() {
return getUsedBytes();
}

abstract UnsignedWord computeInitialValue();

abstract void beforeCollection();
Expand All @@ -77,7 +83,11 @@ MemoryUsage memoryUsage(UnsignedWord usedAndCommitted) {
}

MemoryUsage memoryUsage(UnsignedWord used, UnsignedWord committed) {
return new MemoryUsage(getInitialValue().rawValue(), used.rawValue(), committed.rawValue(), getMaximumValue().rawValue());
return memoryUsage(used.rawValue(), committed.rawValue());
}

public MemoryUsage memoryUsage(long usedAndCommitted, long committed) {
return new MemoryUsage(getInitialValue().rawValue(), usedAndCommitted, committed, getMaximumValue().rawValue());
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,21 +26,16 @@

import java.lang.management.ManagementFactory;

import javax.management.MBeanNotificationInfo;
import javax.management.NotificationEmitter;
import javax.management.NotificationFilter;
import javax.management.NotificationListener;
import javax.management.ObjectName;

import org.graalvm.nativeimage.Platform;
import org.graalvm.nativeimage.Platforms;

import com.oracle.svm.core.util.TimeUtils;
import com.sun.management.GcInfo;

import sun.management.Util;

public final class CompleteGarbageCollectorMXBean implements com.sun.management.GarbageCollectorMXBean, NotificationEmitter {
public final class CompleteGarbageCollectorMXBean extends AbstractGarbageCollectorMXBean {

@Platforms(Platform.HOSTED_ONLY.class)
public CompleteGarbageCollectorMXBean() {
Expand Down Expand Up @@ -81,26 +76,4 @@ public boolean isValid() {
public ObjectName getObjectName() {
return Util.newObjectName(ManagementFactory.GARBAGE_COLLECTOR_MXBEAN_DOMAIN_TYPE, getName());
}

@Override
public void removeNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback) {
}

@Override
public void addNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback) {
}

@Override
public void removeNotificationListener(NotificationListener listener) {
}

@Override
public MBeanNotificationInfo[] getNotificationInfo() {
return new MBeanNotificationInfo[0];
}

@Override
public GcInfo getLastGcInfo() {
return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
import com.oracle.svm.core.genscavenge.HeapChunk.Header;
import com.oracle.svm.core.genscavenge.UnalignedHeapChunk.UnalignedHeader;
import com.oracle.svm.core.genscavenge.remset.RememberedSet;
import com.oracle.svm.core.genscavenge.service.ServiceSupport;
import com.oracle.svm.core.graal.RuntimeCompilation;
import com.oracle.svm.core.heap.CodeReferenceMapDecoder;
import com.oracle.svm.core.heap.GC;
Expand Down Expand Up @@ -103,6 +104,7 @@
import com.oracle.svm.core.threadlocal.VMThreadLocalSupport;
import com.oracle.svm.core.util.TimeUtils;
import com.oracle.svm.core.util.VMError;
import com.oracle.svm.core.VMInspectionOptions;

import jdk.graal.compiler.api.replacements.Fold;

Expand Down Expand Up @@ -240,6 +242,9 @@ assert getCollectionEpoch().equal(data.getRequestingEpoch()) ||
try {
ThreadLocalAllocation.disableAndFlushForAllThreads();
GenScavengeMemoryPoolMXBeans.singleton().notifyBeforeCollection();
if (VMInspectionOptions.hasGcNotificationSupport()) {
ServiceSupport.singleton().beforeCollection(Isolates.getCurrentUptimeMillis());
}
HeapImpl.getAccounting().notifyBeforeCollection();

verifyHeap(Before);
Expand All @@ -257,6 +262,10 @@ assert getCollectionEpoch().equal(data.getRequestingEpoch()) ||
GenScavengeMemoryPoolMXBeans.singleton().notifyAfterCollection();
ChunkBasedCommittedMemoryProvider.get().afterGarbageCollection();

if (VMInspectionOptions.hasGcNotificationSupport()) {
ServiceSupport.singleton().afterCollection(!isCompleteCollection(), cause, getCollectionEpoch(), Isolates.getCurrentUptimeMillis());
}

printGCAfter(cause);
JfrGCHeapSummaryEvent.emit(JfrGCWhen.AFTER_GC);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,13 @@
import jdk.graal.compiler.api.replacements.Fold;

public class GenScavengeMemoryPoolMXBeans {
static final String YOUNG_GEN_SCAVENGER = "young generation scavenger";
static final String COMPLETE_SCAVENGER = "complete scavenger";
public static final String YOUNG_GEN_SCAVENGER = "young generation scavenger";
public static final String COMPLETE_SCAVENGER = "complete scavenger";
static final String EPSILON_SCAVENGER = "epsilon scavenger";

static final String EDEN_SPACE = "eden space";
static final String SURVIVOR_SPACE = "survivor space";
static final String OLD_GEN_SPACE = "old generation space";
public static final String OLD_GEN_SPACE = "old generation space";
static final String EPSILON_HEAP = "epsilon heap";

private final AbstractMemoryPoolMXBean[] mxBeans;
Expand Down Expand Up @@ -125,9 +125,16 @@ public MemoryUsage getCollectionUsage() {
return memoryUsage(WordFactory.zero());
}

@Override
public long getUsedBytes() {
return getCurrentUsage().rawValue();
}

private static UnsignedWord getCurrentUsage() {
return HeapImpl.getAccounting().getEdenUsedBytes();
}


}

static final class SurvivorMemoryPoolMXBean extends AbstractMemoryPoolMXBean {
Expand Down Expand Up @@ -166,6 +173,11 @@ public MemoryUsage getPeakUsage() {
public MemoryUsage getCollectionUsage() {
return memoryUsage(HeapImpl.getAccounting().getSurvivorUsedBytes());
}

@Override
public long getUsedBytes() {
return HeapImpl.getAccounting().getSurvivorUsedBytes().rawValue();
}
}

static final class OldGenerationMemoryPoolMXBean extends AbstractMemoryPoolMXBean {
Expand Down Expand Up @@ -204,6 +216,11 @@ public MemoryUsage getPeakUsage() {
public MemoryUsage getCollectionUsage() {
return memoryUsage(HeapImpl.getAccounting().getOldUsedBytes());
}

@Override
public long getUsedBytes() {
return HeapImpl.getAccounting().getOldUsedBytes().rawValue();
}
}

static final class EpsilonMemoryPoolMXBean extends AbstractMemoryPoolMXBean {
Expand Down Expand Up @@ -243,5 +260,15 @@ public MemoryUsage getPeakUsage() {
public MemoryUsage getCollectionUsage() {
return memoryUsage(WordFactory.zero());
}

@Override
public long getUsedBytes() {
return HeapImpl.getAccounting().getUsedBytes().rawValue();
}

@Override
public long getCommittedBytes() {
return HeapImpl.getAccounting().getCommittedBytes().rawValue();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ public void notifyAfterCollection() {
invalidData = false;
}

HeapSizes getHeapSizesBeforeGc() {
public HeapSizes getHeapSizesBeforeGc() {
return beforeGc;
}

Expand Down Expand Up @@ -136,11 +136,11 @@ public UnsignedWord getCommittedBytes() {
return getUsedBytes().add(getBytesInUnusedChunks());
}

static class HeapSizes {
UnsignedWord eden;
UnsignedWord survivor;
UnsignedWord old;
UnsignedWord free;
public static class HeapSizes {
public UnsignedWord eden;
public UnsignedWord survivor;
public UnsignedWord old;
public UnsignedWord free;

@Platforms(Platform.HOSTED_ONLY.class)
HeapSizes() {
Expand Down
Loading

0 comments on commit 1b5236a

Please sign in to comment.