From cd76733349489f04895bd95c80ce08c24c1d2b4e Mon Sep 17 00:00:00 2001 From: Zhengyu Gu Date: Thu, 10 Feb 2022 11:27:23 -0500 Subject: [PATCH 1/2] Implementation of GarbageCollection event --- .../oracle/svm/core/genscavenge/GCImpl.java | 4 +- .../core/genscavenge/GenScavengeGCName.java | 46 ++++++++++ .../core/genscavenge/JfrGCEventSupport.java | 38 +++++++- .../src/com/oracle/svm/core/heap/GCCause.java | 6 +- .../src/com/oracle/svm/core/heap/GCName.java | 88 +++++++++++++++++++ .../src/com/oracle/svm/core/jfr/JfrEvent.java | 1 + .../src/com/oracle/svm/core/jfr/JfrType.java | 6 +- .../svm/core/jfr/JfrTypeRepository.java | 42 ++++++++- .../src/com/oracle/svm/test/jfr/JFRTest.java | 68 +++++++++++--- .../oracle/svm/test/jfr/TestClassEvent.java | 11 ++- .../com/oracle/svm/test/jfr/TestGCEvents.java | 45 ++++++++++ .../oracle/svm/test/jfr/TestStringEvent.java | 10 ++- .../oracle/svm/test/jfr/TestThreadEvent.java | 10 ++- .../com/oracle/svm/test/jfr/utils/JFR.java | 10 ++- .../svm/test/jfr/utils/JFRFileParser.java | 9 +- .../oracle/svm/test/jfr/utils/LocalJFR.java | 20 +++-- .../GCCauseConstantPoolParser.java | 44 ++++++++++ .../poolparsers/GCNameConstantPoolParser.java | 44 ++++++++++ 18 files changed, 462 insertions(+), 40 deletions(-) create mode 100644 substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GenScavengeGCName.java create mode 100644 substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/GCName.java create mode 100644 substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/jfr/TestGCEvents.java create mode 100644 substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/jfr/utils/poolparsers/GCCauseConstantPoolParser.java create mode 100644 substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/jfr/utils/poolparsers/GCNameConstantPoolParser.java diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCImpl.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCImpl.java index db2af5ae1539..2cf8dd7e51cd 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCImpl.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCImpl.java @@ -209,7 +209,7 @@ private boolean collectImpl(GCCause cause, long requestingNanoTime, boolean forc NoAllocationVerifier nav = noAllocationVerifier.open(); try { - long startTicks = JfrGCEventSupport.startGCPhasePause(); + long startTicks = JfrGCEventSupport.getTicks(); try { outOfMemory = doCollectImpl(cause, requestingNanoTime, forceFullGC, false); if (outOfMemory) { @@ -223,7 +223,7 @@ private boolean collectImpl(GCCause cause, long requestingNanoTime, boolean forc } } } finally { - JfrGCEventSupport.emitGCPhasePauseEvent(getCollectionEpoch(), cause.getName(), startTicks); + JfrGCEventSupport.emitGarbageCollectionEvent(getCollectionEpoch(), cause, startTicks); } } finally { nav.close(); diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GenScavengeGCName.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GenScavengeGCName.java new file mode 100644 index 000000000000..c1d44b52a91c --- /dev/null +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GenScavengeGCName.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2022, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2022, 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.heap.GCName; +import com.oracle.svm.core.SubstrateOptions; + +final class GenScavengeGCName extends GCName { + public static final GCName GenScavenge; + + static { + if (SubstrateOptions.UseEpsilonGC.getValue()) { + GenScavenge = new GenScavengeGCName("epsilon"); + } else { + assert SubstrateOptions.UseSerialGC.getValue(); + GenScavenge = new GenScavengeGCName("serial"); + } + } + + private GenScavengeGCName(String name) { + super(name); + } +} diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/JfrGCEventSupport.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/JfrGCEventSupport.java index 659a382c0f11..9e88c05c868b 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/JfrGCEventSupport.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/JfrGCEventSupport.java @@ -30,12 +30,11 @@ import org.graalvm.word.UnsignedWord; import com.oracle.svm.core.annotate.Uninterruptible; -import com.oracle.svm.core.jfr.JfrBuffer; +import com.oracle.svm.core.heap.GCCause; import com.oracle.svm.core.jfr.JfrEvent; import com.oracle.svm.core.jfr.JfrNativeEventWriter; import com.oracle.svm.core.jfr.JfrNativeEventWriterData; import com.oracle.svm.core.jfr.JfrNativeEventWriterDataAccess; -import com.oracle.svm.core.jfr.JfrThreadLocal; import com.oracle.svm.core.jfr.JfrTicks; import com.oracle.svm.core.jfr.SubstrateJVM; import com.oracle.svm.core.util.VMError; @@ -44,6 +43,13 @@ class JfrGCEventSupport { private static final int MAX_PHASE_LEVEL = 4; private static int currentPhase; + public static long getTicks() { + if (!HasJfrSupport.get()) { + return 0; + } + return JfrTicks.elapsedTicks(); + } + public static long startGCPhasePause() { if (!HasJfrSupport.get()) { return 0; @@ -52,6 +58,31 @@ public static long startGCPhasePause() { return JfrTicks.elapsedTicks(); } + @Uninterruptible(reason = "Accesses a JFR buffer.") + public static void emitGarbageCollectionEvent(UnsignedWord gcEpoch, GCCause cause, long start) { + if (!HasJfrSupport.get()) { + return; + } + + long end = JfrTicks.elapsedTicks(); + long pauseTime = end - start; + if (SubstrateJVM.isRecording() && SubstrateJVM.get().isEnabled(JfrEvent.GarbageCollection)) { + JfrNativeEventWriterData data = StackValue.get(JfrNativeEventWriterData.class); + JfrNativeEventWriterDataAccess.initializeThreadLocalNativeBuffer(data); + + JfrNativeEventWriter.beginEventWrite(data, false); + JfrNativeEventWriter.putLong(data, JfrEvent.GarbageCollection.getId()); + JfrNativeEventWriter.putLong(data, start); + JfrNativeEventWriter.putLong(data, pauseTime); + JfrNativeEventWriter.putLong(data, gcEpoch.rawValue()); + JfrNativeEventWriter.putLong(data, GenScavengeGCName.GenScavenge.getId()); + JfrNativeEventWriter.putLong(data, cause.getId()); + JfrNativeEventWriter.putLong(data, pauseTime); // sum of pause + JfrNativeEventWriter.putLong(data, pauseTime); // longest pause + JfrNativeEventWriter.endEventWrite(data, false); + } + } + @Uninterruptible(reason = "Accesses a JFR buffer.") public static void emitGCPhasePauseEvent(UnsignedWord gcEpoch, String name, long startTicks) { if (!HasJfrSupport.get()) { @@ -62,9 +93,8 @@ public static void emitGCPhasePauseEvent(UnsignedWord gcEpoch, String name, long JfrEvent event = getGCPhasePauseEvent(level); if (SubstrateJVM.isRecording() && SubstrateJVM.get().isEnabled(event)) { long end = JfrTicks.elapsedTicks(); - JfrBuffer buffer = ((JfrThreadLocal) SubstrateJVM.getThreadLocal()).getNativeBuffer(); JfrNativeEventWriterData data = StackValue.get(JfrNativeEventWriterData.class); - JfrNativeEventWriterDataAccess.initialize(data, buffer); + JfrNativeEventWriterDataAccess.initializeThreadLocalNativeBuffer(data); JfrNativeEventWriter.beginEventWrite(data, false); JfrNativeEventWriter.putLong(data, event.getId()); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/GCCause.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/GCCause.java index 3afe7c31a838..a095b3e8da38 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/GCCause.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/GCCause.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2022, Oracle and/or its affiliates. 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 @@ -82,6 +82,10 @@ public static GCCause fromId(int causeId) { return GCCauses[causeId]; } + public static GCCause[] getGCCauses() { + return GCCauses; + } + @Platforms(Platform.HOSTED_ONLY.class) public static void cacheReverseMapping() { GCCauses = HostedGCCauseList.toArray(new GCCause[HostedGCCauseList.size()]); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/GCName.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/GCName.java new file mode 100644 index 000000000000..e1beb86b29ff --- /dev/null +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/GCName.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2022, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2022, 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.heap; + +import java.util.ArrayList; +import org.graalvm.nativeimage.Platform; +import org.graalvm.nativeimage.Platforms; +import org.graalvm.nativeimage.hosted.Feature; + +import com.oracle.svm.core.annotate.AutomaticFeature; +import com.oracle.svm.core.annotate.Uninterruptible; +import com.oracle.svm.core.annotate.UnknownObjectField; +/** + * This class holds supported garbage collector names. + */ +public class GCName { + @Platforms(Platform.HOSTED_ONLY.class) private static final ArrayList HostedGCNameList = new ArrayList<>(); + + @UnknownObjectField(types = {GCName[].class}) protected static GCName[] GCNames; + + private final int id; + private final String name; + + @Platforms(Platform.HOSTED_ONLY.class) + protected GCName(String name) { + this.name = name; + this.id = addGCNameMapping(); + } + + @Platforms(Platform.HOSTED_ONLY.class) + private int addGCNameMapping() { + synchronized (HostedGCNameList) { + int newId = HostedGCNameList.size(); + HostedGCNameList.add(newId, this); + return newId; + } + } + + public String getName() { + return name; + } + + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) + public int getId() { + return id; + } + + public static GCName[] getGCNames() { + return GCNames; + } + + @Platforms(Platform.HOSTED_ONLY.class) + public static void cacheReverseMapping() { + GCNames = HostedGCNameList.toArray(new GCName[HostedGCNameList.size()]); + } +} + +@AutomaticFeature +class GCNameFeature implements Feature { + @Override + public void beforeCompilation(BeforeCompilationAccess access) { + GCName.cacheReverseMapping(); + access.registerAsImmutable(GCName.GCNames); + } +} diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrEvent.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrEvent.java index a62a59d476f3..81821ca5beb8 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrEvent.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrEvent.java @@ -45,6 +45,7 @@ public enum JfrEvent { PhysicalMemory("jdk.PhysicalMemory"), ExecutionSample("jdk.ExecutionSample"), NativeMethodSample("jdk.NativeMethodSample"), + GarbageCollection("jdk.GarbageCollection"), GCPhasePauseEvent("jdk.GCPhasePause"), GCPhasePauseLevel1Event("jdk.GCPhasePauseLevel1"), GCPhasePauseLevel2Event("jdk.GCPhasePauseLevel2"), diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrType.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrType.java index 35186925ef20..7709c613591e 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrType.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Oracle and/or its affiliates. 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 @@ -39,7 +39,9 @@ public enum JfrType { Symbol("jdk.types.Symbol"), Module("jdk.types.Module"), Package("jdk.types.Package"), - FrameType("jdk.types.FrameType"); + FrameType("jdk.types.FrameType"), + GCCause("jdk.types.GCCause"), + GCName("jdk.types.GCName"); private final long id; diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrTypeRepository.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrTypeRepository.java index ef913596c2f4..5743cd469a85 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrTypeRepository.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrTypeRepository.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2022, Oracle and/or its affiliates. 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 @@ -35,6 +35,8 @@ import com.oracle.svm.core.SubstrateUtil; import com.oracle.svm.core.annotate.Uninterruptible; +import com.oracle.svm.core.heap.GCCause; +import com.oracle.svm.core.heap.GCName; import com.oracle.svm.core.heap.Heap; import com.oracle.svm.core.jfr.traceid.JfrTraceId; @@ -62,6 +64,8 @@ public int write(JfrChunkWriter writer) { count += writePackages(writer, typeInfo); count += writeModules(writer, typeInfo); count += writeClassLoaders(writer, typeInfo); + count += writeGCCauses(writer); + count += writeGCNames(writer); return count; } @@ -186,6 +190,42 @@ private static int writeClassLoaders(JfrChunkWriter writer, TypeInfo typeInfo) { return NON_EMPTY; } + private static int writeGCCauses(JfrChunkWriter writer) { + // GCCauses has null entries + GCCause[] causes = GCCause.getGCCauses(); + int nonNullItems = 0; + for (int index = 0; index < causes.length; index++) { + if (causes[index] != null) { + nonNullItems++; + } + } + + assert nonNullItems > 0; + + writer.writeCompressedLong(JfrType.GCCause.getId()); + writer.writeCompressedLong(nonNullItems); + for (GCCause cause : causes) { + if (cause != null) { + writer.writeCompressedLong(cause.getId()); + writer.writeString(cause.getName()); + } + } + return NON_EMPTY; + } + + private static int writeGCNames(JfrChunkWriter writer) { + GCName[] gcNames = GCName.getGCNames(); + assert gcNames != null && gcNames.length > 0; + + writer.writeCompressedLong(JfrType.GCName.getId()); + writer.writeCompressedLong(gcNames.length); + for (GCName name : gcNames) { + writer.writeCompressedLong(name.getId()); + writer.writeString(name.getName()); + } + return NON_EMPTY; + } + private static void writeClassLoader(JfrChunkWriter writer, ClassLoader cl, long id) { JfrSymbolRepository symbolRepo = SubstrateJVM.getSymbolRepository(); writer.writeCompressedLong(id); diff --git a/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/jfr/JFRTest.java b/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/jfr/JFRTest.java index 23705a8fcaf2..85f85cc25e87 100644 --- a/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/jfr/JFRTest.java +++ b/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/jfr/JFRTest.java @@ -1,6 +1,6 @@ /* - * Copyright (c) 2021, 2021, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2021, 2021, Red Hat Inc. All rights reserved. + * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2022, 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 @@ -26,7 +26,6 @@ package com.oracle.svm.test.jfr; -import static org.junit.Assert.assertNotNull; import static org.junit.Assume.assumeTrue; import com.oracle.svm.core.jfr.HasJfrSupport; @@ -40,12 +39,13 @@ import com.oracle.svm.test.jfr.utils.JFRFileParser; import com.oracle.svm.test.jfr.utils.LocalJFR; +import java.util.HashSet; import jdk.jfr.Recording; +import jdk.jfr.consumer.RecordedEvent; import jdk.jfr.consumer.RecordingFile; /** Base class for JFR unit tests. */ public abstract class JFRTest { - protected JFR jfr; protected Recording recording; @@ -58,7 +58,12 @@ public static void checkForJFR() { public void startRecording() { try { jfr = new LocalJFR(); - recording = jfr.startRecording(getClass().getName()); + recording = jfr.createRecording(getClass().getName()); + + String[] events = getTestEvents(); + setupEvents(events); + + jfr.startRecording(recording); } catch (Exception e) { Assert.fail("Fail to start recording! Cause: " + e.getMessage()); } @@ -68,14 +73,57 @@ public void startRecording() { public void endRecording() { try { jfr.endRecording(recording); - try (RecordingFile recordingFile = new RecordingFile(recording.getDestination())) { - assertNotNull(recordingFile); - JFRFileParser.parse(recording); - } finally { + } catch (Exception e) { + Assert.fail("Fail to stop recording! Cause: " + e.getMessage()); + } + + try { + checkRecording(); + } finally { + try { jfr.cleanupRecording(recording); + } catch (Exception e) { + Assert.fail("Fail to cleanup recording! Cause: " + e.getMessage()); + } + } + } + + protected void setupEvents(String[] events) { + if (events != null) { + for (String event : events) { + recording.enable(event); + } + } + } + + // List events that expects to be recorded + public abstract String[] getTestEvents(); + + protected void checkEvents() { + HashSet seenEvents = new HashSet<>(); + + try (RecordingFile recordingFile = new RecordingFile(recording.getDestination())) { + while (recordingFile.hasMoreEvents()) { + RecordedEvent event = recordingFile.readEvent(); + String eventName = event.getEventType().getName(); + seenEvents.add(eventName); } } catch (Exception e) { - Assert.fail("Fail to stop recording! Cause: " + e.getMessage()); + Assert.fail("Failed to read events: " + e.getMessage()); + } + + for (String name : getTestEvents()) { + if (!seenEvents.contains(name)) { + Assert.fail("Event: " + name + " not found in recording"); + } + } + } + + protected void checkRecording() throws AssertionError { + try { + JFRFileParser.parse(recording); + } catch (Exception e) { + Assert.fail("Failed to parse recording: " + e.getMessage()); } } } diff --git a/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/jfr/TestClassEvent.java b/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/jfr/TestClassEvent.java index eb3bd8d5db83..1492119d4a56 100644 --- a/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/jfr/TestClassEvent.java +++ b/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/jfr/TestClassEvent.java @@ -1,6 +1,6 @@ /* - * Copyright (c) 2021, 2021, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2021, 2021, Red Hat Inc. All rights reserved. + * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2022, 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 @@ -31,6 +31,13 @@ public class TestClassEvent extends JFRTest { + @Override + public String[] getTestEvents() { + return new String[]{ + ClassEvent.class.toString() + }; + } + @Test public void test() throws Exception { ClassEvent event = new ClassEvent(); diff --git a/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/jfr/TestGCEvents.java b/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/jfr/TestGCEvents.java new file mode 100644 index 000000000000..23540f5a8b58 --- /dev/null +++ b/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/jfr/TestGCEvents.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2022, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2022, 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.test.jfr; + +import org.junit.Test; + +public class TestGCEvents extends JFRTest { + @Override + public String[] getTestEvents() { + return new String[]{ + "jdk.GarbageCollection", + "jdk.GCPhasePause", + "jdk.GCPhasePauseLevel1" + }; + } + + @Test + public void test() throws Exception { + System.gc(); + } +} diff --git a/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/jfr/TestStringEvent.java b/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/jfr/TestStringEvent.java index 94b6848ac947..4b0cb36b2caf 100644 --- a/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/jfr/TestStringEvent.java +++ b/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/jfr/TestStringEvent.java @@ -1,6 +1,6 @@ /* - * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2020, 2021, Red Hat Inc. All rights reserved. + * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, 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 @@ -30,6 +30,12 @@ import org.junit.Test; public class TestStringEvent extends JFRTest { + @Override + public String[] getTestEvents() { + return new String[]{ + StringEvent.class.toString() + }; + } @Test public void test() throws Exception { diff --git a/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/jfr/TestThreadEvent.java b/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/jfr/TestThreadEvent.java index 3143dc2cfffb..6cc475ef6f6b 100644 --- a/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/jfr/TestThreadEvent.java +++ b/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/jfr/TestThreadEvent.java @@ -1,6 +1,6 @@ /* - * Copyright (c) 2021, 2021, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2021, 2021, Red Hat Inc. All rights reserved. + * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2022, 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 @@ -33,6 +33,12 @@ * Test if event ({@link TestThreadEvent}) with {@link Thread} payload is working. */ public class TestThreadEvent extends JFRTest { + @Override + public String[] getTestEvents() { + return new String[]{ + ThreadEvent.class.toString() + }; + } @Test public void test() throws Exception { diff --git a/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/jfr/utils/JFR.java b/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/jfr/utils/JFR.java index 89b212315394..7818f0e88d73 100644 --- a/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/jfr/utils/JFR.java +++ b/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/jfr/utils/JFR.java @@ -1,6 +1,6 @@ /* - * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2020, 2021, Red Hat Inc. All rights reserved. + * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, 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 @@ -35,9 +35,11 @@ */ public interface JFR { - Recording startRecording(String recordingName) throws Exception; + Recording createRecording(String recordingName) throws Exception; - Recording startRecording(String recordingName, String configName) throws Exception; + Recording createRecording(String recordingName, String configName) throws Exception; + + void startRecording(Recording recording); void endRecording(Recording recording) throws Exception; diff --git a/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/jfr/utils/JFRFileParser.java b/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/jfr/utils/JFRFileParser.java index 38510fbc0273..7d42a8611420 100644 --- a/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/jfr/utils/JFRFileParser.java +++ b/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/jfr/utils/JFRFileParser.java @@ -1,6 +1,6 @@ /* - * Copyright (c) 2021, 2021, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2021, 2021, Red Hat Inc. All rights reserved. + * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2022, 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 @@ -40,6 +40,8 @@ import com.oracle.svm.test.jfr.utils.poolparsers.ClassLoaderConstantPoolParser; import com.oracle.svm.test.jfr.utils.poolparsers.ConstantPoolParser; import com.oracle.svm.test.jfr.utils.poolparsers.FrameTypeConstantPoolParser; +import com.oracle.svm.test.jfr.utils.poolparsers.GCCauseConstantPoolParser; +import com.oracle.svm.test.jfr.utils.poolparsers.GCNameConstantPoolParser; import com.oracle.svm.test.jfr.utils.poolparsers.MethodConstantPoolParser; import com.oracle.svm.test.jfr.utils.poolparsers.ModuleConstantPoolParser; import com.oracle.svm.test.jfr.utils.poolparsers.PackageConstantPoolParser; @@ -71,6 +73,9 @@ public class JFRFileParser { supportedConstantPools.put(JfrType.Thread.getId(), new ThreadConstantPoolParser()); supportedConstantPools.put(JfrType.ThreadGroup.getId(), new ThreadGroupConstantPoolParser()); supportedConstantPools.put(JfrType.ThreadState.getId(), new ThreadStateConstantPoolParser()); + + supportedConstantPools.put(JfrType.GCName.getId(), new GCNameConstantPoolParser()); + supportedConstantPools.put(JfrType.GCCause.getId(), new GCCauseConstantPoolParser()); } public static HashMap getSupportedConstantPools() { diff --git a/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/jfr/utils/LocalJFR.java b/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/jfr/utils/LocalJFR.java index 8544e83a5d64..19ebf3f83e88 100644 --- a/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/jfr/utils/LocalJFR.java +++ b/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/jfr/utils/LocalJFR.java @@ -1,6 +1,6 @@ /* - * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2020, 2021, Red Hat Inc. All rights reserved. + * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, 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 @@ -37,23 +37,27 @@ public class LocalJFR implements JFR { @Override - public Recording startRecording(String recordingName) throws Exception { - return startRecording(new Recording(), recordingName); + public Recording createRecording(String recordingName) throws Exception { + return createRecording(new Recording(), recordingName); } @Override - public Recording startRecording(String recordingName, String configName) throws Exception { + public Recording createRecording(String recordingName, String configName) throws Exception { Configuration c = Configuration.getConfiguration(configName); - return startRecording(new Recording(c), recordingName); + return createRecording(new Recording(c), recordingName); } - private static Recording startRecording(Recording recording, String name) throws Exception { + @Override + public void startRecording(Recording recording) { + recording.start(); + } + + private static Recording createRecording(Recording recording, String name) throws Exception { long id = recording.getId(); Path destination = File.createTempFile(name + "-" + id, ".jfr").toPath(); recording.setDestination(destination); - recording.start(); return recording; } diff --git a/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/jfr/utils/poolparsers/GCCauseConstantPoolParser.java b/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/jfr/utils/poolparsers/GCCauseConstantPoolParser.java new file mode 100644 index 000000000000..54143d0879f9 --- /dev/null +++ b/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/jfr/utils/poolparsers/GCCauseConstantPoolParser.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2022, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2022, 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.test.jfr.utils.poolparsers; + +import com.oracle.svm.test.jfr.utils.RecordingInput; +import org.junit.Assert; + +import java.io.IOException; + +public class GCCauseConstantPoolParser extends ConstantPoolParser { + + @Override + public void parse(RecordingInput input) throws IOException { + int numberOfGCCauses = input.readInt(); + for (int i = 0; i < numberOfGCCauses; i++) { + addFoundId(input.readInt()); // Id. + Assert.assertFalse("GCCause name is empty!", input.readUTF().isEmpty()); + } + } +} diff --git a/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/jfr/utils/poolparsers/GCNameConstantPoolParser.java b/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/jfr/utils/poolparsers/GCNameConstantPoolParser.java new file mode 100644 index 000000000000..b309ecde93e7 --- /dev/null +++ b/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/jfr/utils/poolparsers/GCNameConstantPoolParser.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2022, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2022, 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.test.jfr.utils.poolparsers; + +import com.oracle.svm.test.jfr.utils.RecordingInput; +import org.junit.Assert; + +import java.io.IOException; + +public class GCNameConstantPoolParser extends ConstantPoolParser { + + @Override + public void parse(RecordingInput input) throws IOException { + int numberOfGCNames = input.readInt(); + for (int i = 0; i < numberOfGCNames; i++) { + addFoundId(input.readInt()); // Id. + Assert.assertFalse("GC name is empty!", input.readUTF().isEmpty()); + } + } +} From 0cf5017f543bcc81e78392a7e0d1f76cd4f9f253 Mon Sep 17 00:00:00 2001 From: Zhengyu Gu Date: Tue, 15 Feb 2022 16:48:24 -0500 Subject: [PATCH 2/2] Fix style --- .../com.oracle.svm.core/src/com/oracle/svm/core/heap/GCName.java | 1 + 1 file changed, 1 insertion(+) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/GCName.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/GCName.java index e1beb86b29ff..47706defb5a8 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/GCName.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/GCName.java @@ -33,6 +33,7 @@ import com.oracle.svm.core.annotate.AutomaticFeature; import com.oracle.svm.core.annotate.Uninterruptible; import com.oracle.svm.core.annotate.UnknownObjectField; + /** * This class holds supported garbage collector names. */