From 649e1ac6b45824c0a643a28b74be125b65876361 Mon Sep 17 00:00:00 2001 From: Jonas Norlinder Date: Mon, 22 Sep 2025 14:12:41 +0200 Subject: [PATCH 01/14] Add GC CPU MXBeans --- src/hotspot/share/include/jmm.h | 6 +- src/hotspot/share/services/cpuTimeUsage.cpp | 1 + src/hotspot/share/services/management.cpp | 19 +++++ .../java/lang/management/MemoryMXBean.java | 21 ++++- .../classes/sun/management/MemoryImpl.java | 4 + .../classes/sun/management/VMManagement.java | 1 + .../sun/management/VMManagementImpl.java | 2 + .../native/libmanagement/VMManagementImpl.c | 7 ++ .../share/server/ServerMemoryMXBean.java | 4 + .../management/MemoryMXBean/GetGcCpuTime.java | 83 +++++++++++++++++++ .../management/mxbean/MXBeanInteropTest1.java | 2 + 11 files changed, 146 insertions(+), 4 deletions(-) create mode 100644 test/jdk/java/lang/management/MemoryMXBean/GetGcCpuTime.java diff --git a/src/hotspot/share/include/jmm.h b/src/hotspot/share/include/jmm.h index ba7ed3bbca52c..60b04daef7f25 100644 --- a/src/hotspot/share/include/jmm.h +++ b/src/hotspot/share/include/jmm.h @@ -53,7 +53,8 @@ enum { JMM_VERSION_2 = 0x20020000, // JDK 10 JMM_VERSION_3 = 0x20030000, // JDK 14 JMM_VERSION_4 = 0x20040000, // JDK 21 - JMM_VERSION = JMM_VERSION_4 + JMM_VERSION_5 = 0x20050000, // JDK 26 + JMM_VERSION = JMM_VERSION_5 }; typedef struct { @@ -80,7 +81,8 @@ typedef enum { JMM_COMPILE_TOTAL_TIME_MS = 8, /* Total accumulated time spent in compilation */ JMM_GC_TIME_MS = 9, /* Total accumulated time spent in collection */ JMM_GC_COUNT = 10, /* Total number of collections */ - JMM_JVM_UPTIME_MS = 11, /* The JVM uptime in milliseconds */ + JMM_GC_CPU_TIME = 11, /* Total accumulated GC CPU time */ + JMM_JVM_UPTIME_MS = 12, /* The JVM uptime in milliseconds */ JMM_INTERNAL_ATTRIBUTE_INDEX = 100, JMM_CLASS_LOADED_BYTES = 101, /* Number of bytes loaded instance classes */ diff --git a/src/hotspot/share/services/cpuTimeUsage.cpp b/src/hotspot/share/services/cpuTimeUsage.cpp index 27b5e90fbaf56..0c7ecfdb6558b 100644 --- a/src/hotspot/share/services/cpuTimeUsage.cpp +++ b/src/hotspot/share/services/cpuTimeUsage.cpp @@ -36,6 +36,7 @@ volatile bool CPUTimeUsage::Error::_has_error = false; static inline jlong thread_cpu_time_or_zero(Thread* thread) { + assert(!Universe::is_shutting_down(), "Should not query during shutdown"); jlong cpu_time = os::thread_cpu_time(thread); if (cpu_time == -1) { CPUTimeUsage::Error::mark_error(); diff --git a/src/hotspot/share/services/management.cpp b/src/hotspot/share/services/management.cpp index cfe13d0c8f1e5..11a3e2ef75c3e 100644 --- a/src/hotspot/share/services/management.cpp +++ b/src/hotspot/share/services/management.cpp @@ -54,6 +54,7 @@ #include "runtime/threadSMR.hpp" #include "runtime/vmOperations.hpp" #include "services/classLoadingService.hpp" +#include "services/cpuTimeUsage.hpp" #include "services/diagnosticCommand.hpp" #include "services/diagnosticFramework.hpp" #include "services/finalizerService.hpp" @@ -889,6 +890,21 @@ static jint get_num_flags() { return count; } +static jlong get_gc_cpu_time() { + if (!os::is_thread_cpu_time_supported()) { + return -1; + } + + { + MutexLocker hl(Heap_lock); + if (Universe::heap()->is_shutting_down()) { + return -1; + } + + return CPUTimeUsage::GC::total(); + } +} + static jlong get_long_attribute(jmmLongAttribute att) { switch (att) { case JMM_CLASS_LOADED_COUNT: @@ -915,6 +931,9 @@ static jlong get_long_attribute(jmmLongAttribute att) { case JMM_JVM_UPTIME_MS: return Management::ticks_to_ms(os::elapsed_counter()); + case JMM_GC_CPU_TIME: + return get_gc_cpu_time(); + case JMM_COMPILE_TOTAL_TIME_MS: return Management::ticks_to_ms(CompileBroker::total_compilation_ticks()); diff --git a/src/java.management/share/classes/java/lang/management/MemoryMXBean.java b/src/java.management/share/classes/java/lang/management/MemoryMXBean.java index 2c982e1ce9c67..71bb4a67b1347 100644 --- a/src/java.management/share/classes/java/lang/management/MemoryMXBean.java +++ b/src/java.management/share/classes/java/lang/management/MemoryMXBean.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, 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 @@ -267,6 +267,24 @@ public interface MemoryMXBean extends PlatformManagedObject { */ public MemoryUsage getNonHeapMemoryUsage(); + /** + * Returns the CPU time used by all garbage collection threads. + * + *

This include time since genesis, so the value can be + * non-zero even if no garbage collection cycles occured. In + * general this includes time for all driver threads, + * workers, VM operations on the VM thread and the string + * deduplication thread (if enabled). This method returns + * {@code -1} if the platform does not support this operation + * or if called during shutdown. + * + * @return the total CPU time for all garbage collection + * threads in nanoseconds. + * + * @since 26 + */ + public long getGcCpuTime(); + /** * Tests if verbose output for the memory system is enabled. * @@ -302,5 +320,4 @@ public interface MemoryMXBean extends PlatformManagedObject { * @see java.lang.System#gc() */ public void gc(); - } diff --git a/src/java.management/share/classes/sun/management/MemoryImpl.java b/src/java.management/share/classes/sun/management/MemoryImpl.java index e1f68ce3711db..748a36c5434d3 100644 --- a/src/java.management/share/classes/sun/management/MemoryImpl.java +++ b/src/java.management/share/classes/sun/management/MemoryImpl.java @@ -67,6 +67,10 @@ public void gc() { Runtime.getRuntime().gc(); } + public long getGcCpuTime() { + return jvm.getGcCpuTime(); + } + // Need to make a VM call to get coherent value public MemoryUsage getHeapMemoryUsage() { return getMemoryUsage0(true); diff --git a/src/java.management/share/classes/sun/management/VMManagement.java b/src/java.management/share/classes/sun/management/VMManagement.java index f4445f0225af3..3d1af88666274 100644 --- a/src/java.management/share/classes/sun/management/VMManagement.java +++ b/src/java.management/share/classes/sun/management/VMManagement.java @@ -55,6 +55,7 @@ public interface VMManagement { public boolean getVerboseClass(); // Memory Subsystem + public long getGcCpuTime(); public boolean getVerboseGC(); // Runtime Subsystem diff --git a/src/java.management/share/classes/sun/management/VMManagementImpl.java b/src/java.management/share/classes/sun/management/VMManagementImpl.java index 041f09547d2ba..80a39ebd4719e 100644 --- a/src/java.management/share/classes/sun/management/VMManagementImpl.java +++ b/src/java.management/share/classes/sun/management/VMManagementImpl.java @@ -33,6 +33,7 @@ import java.net.InetAddress; import java.net.UnknownHostException; import java.util.List; + import java.util.Arrays; import java.util.Collections; @@ -128,6 +129,7 @@ public int getLoadedClassCount() { public native boolean getVerboseClass(); // Memory Subsystem + public native long getGcCpuTime(); public native boolean getVerboseGC(); // Runtime Subsystem diff --git a/src/java.management/share/native/libmanagement/VMManagementImpl.c b/src/java.management/share/native/libmanagement/VMManagementImpl.c index f1a566676dceb..b4ae7aca8e200 100644 --- a/src/java.management/share/native/libmanagement/VMManagementImpl.c +++ b/src/java.management/share/native/libmanagement/VMManagementImpl.c @@ -121,6 +121,13 @@ Java_sun_management_VMManagementImpl_getUnloadedClassCount return count; } +JNIEXPORT jlong JNICALL +Java_sun_management_VMManagementImpl_getGcCpuTime + (JNIEnv *env, jobject dummy) +{ + return jmm_interface->GetLongAttribute(env, NULL, JMM_GC_CPU_TIME); +} + JNIEXPORT jboolean JNICALL Java_sun_management_VMManagementImpl_getVerboseGC (JNIEnv *env, jobject dummy) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/share/server/ServerMemoryMXBean.java b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/share/server/ServerMemoryMXBean.java index 0c536fcd12367..fa4c43ac5735d 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/share/server/ServerMemoryMXBean.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/share/server/ServerMemoryMXBean.java @@ -58,6 +58,10 @@ public int getObjectPendingFinalizationCount() { return getIntAttribute(OBJECT_PENDING_FINALIZATION_COUNT); } + public long getGcCpuTime() { + throw new UnsupportedOperationException("This method is not supported"); + } + public boolean isVerbose() { return getBooleanAttribute(VERBOSE); } diff --git a/test/jdk/java/lang/management/MemoryMXBean/GetGcCpuTime.java b/test/jdk/java/lang/management/MemoryMXBean/GetGcCpuTime.java new file mode 100644 index 0000000000000..1f73d6a04b6ac --- /dev/null +++ b/test/jdk/java/lang/management/MemoryMXBean/GetGcCpuTime.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2025, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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. + */ + +/* + * @test + * @bug 8368527 + * @library /test/lib + * @summary Stress MemoryMXBean.getGcCpuTime during shutdown + * + * @run main/othervm -XX:+UseSerialGC GetGcCpuTime _ + * @run main/othervm -XX:+UseParallelGC GetGcCpuTime _ + * @run main/othervm -XX:+UseG1GC GetGcCpuTime _ + * @run main/othervm -XX:+UseZGC GetGcCpuTime _ + */ + +import jdk.test.lib.process.OutputAnalyzer; +import static jdk.test.lib.process.ProcessTools.createTestJavaProcessBuilder; +import static jdk.test.lib.process.ProcessTools.executeProcess; + +import java.lang.management.ManagementFactory; +import java.lang.management.MemoryMXBean; +import java.lang.management.ThreadMXBean; + +public class GetGcCpuTime { + static final ThreadMXBean mxThreadBean = ManagementFactory.getThreadMXBean(); + static final MemoryMXBean mxMemoryBean = ManagementFactory.getMemoryMXBean(); + + public static void main(String[] args) throws Exception { + if (args.length > 0) { + ProcessBuilder pb = createTestJavaProcessBuilder("GetGcCpuTime"); + OutputAnalyzer output = executeProcess(pb); + output.shouldNotContain("GC CPU time should"); + output.shouldHaveExitValue(0); + return; + } + + try { + if (!mxThreadBean.isThreadCpuTimeEnabled()) { + return; + } + } catch (UnsupportedOperationException e) { + if (mxMemoryBean.getGcCpuTime() != -1) { + throw new Error("GC CPU time should be -1"); + } + return; + } + + final int numberOfThreads = Runtime.getRuntime().availableProcessors() * 8; + for (int i = 0; i < numberOfThreads; i++) { + Thread t = new Thread(() -> { + while (true) { + long gcCpuTimeFromThread = mxMemoryBean.getGcCpuTime(); + if (gcCpuTimeFromThread < -1) { + throw new Error("GC CPU time should never be less than -1 but was " + gcCpuTimeFromThread); + } + } + }); + t.start(); + } + + System.exit(0); + } +} diff --git a/test/jdk/javax/management/mxbean/MXBeanInteropTest1.java b/test/jdk/javax/management/mxbean/MXBeanInteropTest1.java index 500fef1c2f319..014b748b0d67f 100644 --- a/test/jdk/javax/management/mxbean/MXBeanInteropTest1.java +++ b/test/jdk/javax/management/mxbean/MXBeanInteropTest1.java @@ -222,6 +222,8 @@ private final int doMemoryMXBeanTest(MBeanServerConnection mbsc) { + memory.getNonHeapMemoryUsage()); System.out.println("getObjectPendingFinalizationCount\t\t" + memory.getObjectPendingFinalizationCount()); + System.out.println("getGcCpuTime\t\t" + + memory.getGcCpuTime()); System.out.println("isVerbose\t\t" + memory.isVerbose()); From ae29e031dcfee0f2ff01197995d831de8d973ad7 Mon Sep 17 00:00:00 2001 From: Jonas Norlinder Date: Sat, 27 Sep 2025 18:29:51 +0200 Subject: [PATCH 02/14] Remove extra new line --- .../share/classes/sun/management/VMManagementImpl.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/java.management/share/classes/sun/management/VMManagementImpl.java b/src/java.management/share/classes/sun/management/VMManagementImpl.java index 80a39ebd4719e..7ede618b2f21e 100644 --- a/src/java.management/share/classes/sun/management/VMManagementImpl.java +++ b/src/java.management/share/classes/sun/management/VMManagementImpl.java @@ -33,7 +33,6 @@ import java.net.InetAddress; import java.net.UnknownHostException; import java.util.List; - import java.util.Arrays; import java.util.Collections; From 6431310109a02ec5c34f877a1c690afb00193043 Mon Sep 17 00:00:00 2001 From: Jonas Norlinder Date: Sun, 5 Oct 2025 14:27:30 +0200 Subject: [PATCH 03/14] Move from j.l.management to com.sun.management etc. --- src/hotspot/share/include/jmm.h | 4 +- .../java/lang/management/MemoryMXBean.java | 21 +------- .../classes/sun/management/MemoryImpl.java | 10 ++-- .../classes/sun/management/VMManagement.java | 2 +- .../sun/management/VMManagementImpl.java | 2 +- .../native/libmanagement/VMManagementImpl.c | 2 +- .../com/sun/management/MemoryMXBean.java | 53 +++++++++++++++++++ .../internal/HotSpotMemoryImpl.java | 43 +++++++++++++++ .../internal/PlatformMBeanProviderImpl.java | 44 +++++++++++++++ .../share/server/ServerMemoryMXBean.java | 4 -- .../MemoryMXBean/GetTotalGcCpuTime.java} | 23 ++++---- .../management/mxbean/MXBeanInteropTest1.java | 2 - 12 files changed, 162 insertions(+), 48 deletions(-) create mode 100644 src/jdk.management/share/classes/com/sun/management/MemoryMXBean.java create mode 100644 src/jdk.management/share/classes/com/sun/management/internal/HotSpotMemoryImpl.java rename test/jdk/{java/lang/management/MemoryMXBean/GetGcCpuTime.java => com/sun/management/MemoryMXBean/GetTotalGcCpuTime.java} (82%) diff --git a/src/hotspot/share/include/jmm.h b/src/hotspot/share/include/jmm.h index 60b04daef7f25..efe4aef0229a9 100644 --- a/src/hotspot/share/include/jmm.h +++ b/src/hotspot/share/include/jmm.h @@ -81,8 +81,8 @@ typedef enum { JMM_COMPILE_TOTAL_TIME_MS = 8, /* Total accumulated time spent in compilation */ JMM_GC_TIME_MS = 9, /* Total accumulated time spent in collection */ JMM_GC_COUNT = 10, /* Total number of collections */ - JMM_GC_CPU_TIME = 11, /* Total accumulated GC CPU time */ - JMM_JVM_UPTIME_MS = 12, /* The JVM uptime in milliseconds */ + JMM_JVM_UPTIME_MS = 11, /* The JVM uptime in milliseconds */ + JMM_GC_CPU_TIME = 12, /* Total accumulated GC CPU time */ JMM_INTERNAL_ATTRIBUTE_INDEX = 100, JMM_CLASS_LOADED_BYTES = 101, /* Number of bytes loaded instance classes */ diff --git a/src/java.management/share/classes/java/lang/management/MemoryMXBean.java b/src/java.management/share/classes/java/lang/management/MemoryMXBean.java index 71bb4a67b1347..2c982e1ce9c67 100644 --- a/src/java.management/share/classes/java/lang/management/MemoryMXBean.java +++ b/src/java.management/share/classes/java/lang/management/MemoryMXBean.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, 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 @@ -267,24 +267,6 @@ public interface MemoryMXBean extends PlatformManagedObject { */ public MemoryUsage getNonHeapMemoryUsage(); - /** - * Returns the CPU time used by all garbage collection threads. - * - *

This include time since genesis, so the value can be - * non-zero even if no garbage collection cycles occured. In - * general this includes time for all driver threads, - * workers, VM operations on the VM thread and the string - * deduplication thread (if enabled). This method returns - * {@code -1} if the platform does not support this operation - * or if called during shutdown. - * - * @return the total CPU time for all garbage collection - * threads in nanoseconds. - * - * @since 26 - */ - public long getGcCpuTime(); - /** * Tests if verbose output for the memory system is enabled. * @@ -320,4 +302,5 @@ public interface MemoryMXBean extends PlatformManagedObject { * @see java.lang.System#gc() */ public void gc(); + } diff --git a/src/java.management/share/classes/sun/management/MemoryImpl.java b/src/java.management/share/classes/sun/management/MemoryImpl.java index 748a36c5434d3..bc481acfe83bf 100644 --- a/src/java.management/share/classes/sun/management/MemoryImpl.java +++ b/src/java.management/share/classes/sun/management/MemoryImpl.java @@ -43,10 +43,10 @@ * ManagementFactory.getMemoryMXBean() returns an instance * of this class. */ -class MemoryImpl extends NotificationEmitterSupport +public class MemoryImpl extends NotificationEmitterSupport implements MemoryMXBean { - private final VMManagement jvm; + protected final VMManagement jvm; private static MemoryPoolMXBean[] pools = null; private static MemoryManagerMXBean[] mgrs = null; @@ -54,7 +54,7 @@ class MemoryImpl extends NotificationEmitterSupport /** * Constructor of MemoryImpl class */ - MemoryImpl(VMManagement vm) { + protected MemoryImpl(VMManagement vm) { this.jvm = vm; } @@ -67,10 +67,6 @@ public void gc() { Runtime.getRuntime().gc(); } - public long getGcCpuTime() { - return jvm.getGcCpuTime(); - } - // Need to make a VM call to get coherent value public MemoryUsage getHeapMemoryUsage() { return getMemoryUsage0(true); diff --git a/src/java.management/share/classes/sun/management/VMManagement.java b/src/java.management/share/classes/sun/management/VMManagement.java index 3d1af88666274..3e227225ccd65 100644 --- a/src/java.management/share/classes/sun/management/VMManagement.java +++ b/src/java.management/share/classes/sun/management/VMManagement.java @@ -55,7 +55,7 @@ public interface VMManagement { public boolean getVerboseClass(); // Memory Subsystem - public long getGcCpuTime(); + public long getTotalGcCpuTime(); public boolean getVerboseGC(); // Runtime Subsystem diff --git a/src/java.management/share/classes/sun/management/VMManagementImpl.java b/src/java.management/share/classes/sun/management/VMManagementImpl.java index 7ede618b2f21e..b8c7a2921d477 100644 --- a/src/java.management/share/classes/sun/management/VMManagementImpl.java +++ b/src/java.management/share/classes/sun/management/VMManagementImpl.java @@ -128,7 +128,7 @@ public int getLoadedClassCount() { public native boolean getVerboseClass(); // Memory Subsystem - public native long getGcCpuTime(); + public native long getTotalGcCpuTime(); public native boolean getVerboseGC(); // Runtime Subsystem diff --git a/src/java.management/share/native/libmanagement/VMManagementImpl.c b/src/java.management/share/native/libmanagement/VMManagementImpl.c index b4ae7aca8e200..f7cedff03a4e4 100644 --- a/src/java.management/share/native/libmanagement/VMManagementImpl.c +++ b/src/java.management/share/native/libmanagement/VMManagementImpl.c @@ -122,7 +122,7 @@ Java_sun_management_VMManagementImpl_getUnloadedClassCount } JNIEXPORT jlong JNICALL -Java_sun_management_VMManagementImpl_getGcCpuTime +Java_sun_management_VMManagementImpl_getTotalGcCpuTime (JNIEnv *env, jobject dummy) { return jmm_interface->GetLongAttribute(env, NULL, JMM_GC_CPU_TIME); diff --git a/src/jdk.management/share/classes/com/sun/management/MemoryMXBean.java b/src/jdk.management/share/classes/com/sun/management/MemoryMXBean.java new file mode 100644 index 0000000000000..5444d7e8e0f5c --- /dev/null +++ b/src/jdk.management/share/classes/com/sun/management/MemoryMXBean.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2025, 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 + * 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.sun.management; + +/** + * Platform-specific management interface for the memory + * system on which the Java virtual machine is running. + * + * @since 26 + */ + +public interface MemoryMXBean extends java.lang.management.MemoryMXBean { + /** + * Returns the CPU time used by garbage collection. + * + *

CPU time used by all garbage collection. In + * general this includes time for all driver threads, + * workers, VM operations on the VM thread and the string + * deduplication thread (if enabled). May be non-zero even if no + * GC cycle occurred. This method returns {@code -1} if the + * platform does not support this operation or if called during + * shutdown. + * + * @return the total accumulated CPU time for garbage collection + * in nanoseconds. + * + * @since 26 + */ + public long getTotalGcCpuTime(); +} diff --git a/src/jdk.management/share/classes/com/sun/management/internal/HotSpotMemoryImpl.java b/src/jdk.management/share/classes/com/sun/management/internal/HotSpotMemoryImpl.java new file mode 100644 index 0000000000000..64d072eb4ce58 --- /dev/null +++ b/src/jdk.management/share/classes/com/sun/management/internal/HotSpotMemoryImpl.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2025, 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 + * 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.sun.management.internal; + +import com.sun.management.MemoryMXBean; +import sun.management.ManagementFactoryHelper; +import sun.management.MemoryImpl; +import sun.management.VMManagement; + +/** + * Implementation of the Memory MBean for Hotspot VM. + */ +public class HotSpotMemoryImpl extends MemoryImpl implements MemoryMXBean { + public HotSpotMemoryImpl(VMManagement vm) { + super(ManagementFactoryHelper.getVMManagement()); + } + + public long getTotalGcCpuTime() { + return jvm.getTotalGcCpuTime(); + } +} diff --git a/src/jdk.management/share/classes/com/sun/management/internal/PlatformMBeanProviderImpl.java b/src/jdk.management/share/classes/com/sun/management/internal/PlatformMBeanProviderImpl.java index 3a64fe6b858fe..9e903f2b87106 100644 --- a/src/jdk.management/share/classes/com/sun/management/internal/PlatformMBeanProviderImpl.java +++ b/src/jdk.management/share/classes/com/sun/management/internal/PlatformMBeanProviderImpl.java @@ -29,6 +29,7 @@ import com.sun.management.ThreadMXBean; import java.lang.management.ManagementFactory; import java.lang.management.MemoryManagerMXBean; +import java.lang.management.MemoryMXBean; import java.lang.management.OperatingSystemMXBean; import java.util.ArrayList; import java.util.Collections; @@ -51,6 +52,7 @@ public final class PlatformMBeanProviderImpl extends PlatformMBeanProvider { private final List> mxbeanList; private static HotSpotDiagnostic hsDiagMBean = null; private static OperatingSystemMXBean osMBean = null; + private static MemoryMXBean memoryMBean = null; static { System.loadLibrary("management_ext"); @@ -194,6 +196,41 @@ public Map nameToMBeanMap() { } }); + /** + * MemoryMXBean + */ + initMBeanList.add(new PlatformComponent() { + private final Set memoryMXBeanInterfaceNames + = Collections.unmodifiableSet( + Stream.of("java.lang.management.MemoryMXBean", + "com.sun.management.MemoryMXBean") + .collect(Collectors.toSet())); + + @Override + public Set> mbeanInterfaces() { + return Stream.of(java.lang.management.MemoryMXBean.class, + com.sun.management.MemoryMXBean.class) + .collect(Collectors.toSet()); + } + + @Override + public Set mbeanInterfaceNames() { + return memoryMXBeanInterfaceNames; + } + + @Override + public String getObjectNamePattern() { + return ManagementFactory.MEMORY_MXBEAN_NAME; + } + + @Override + public Map nameToMBeanMap() { + return Collections.singletonMap( + ManagementFactory.MEMORY_MXBEAN_NAME, + getMemoryMXBean()); + } + }); + /** * OperatingSystemMXBean */ @@ -312,4 +349,11 @@ private static synchronized OperatingSystemMXBean getOperatingSystemMXBean() { } return osMBean; } + + private static synchronized MemoryMXBean getMemoryMXBean() { + if (memoryMBean == null) { + memoryMBean = new HotSpotMemoryImpl(ManagementFactoryHelper.getVMManagement()); + } + return memoryMBean; + } } diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/share/server/ServerMemoryMXBean.java b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/share/server/ServerMemoryMXBean.java index fa4c43ac5735d..0c536fcd12367 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/share/server/ServerMemoryMXBean.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/share/server/ServerMemoryMXBean.java @@ -58,10 +58,6 @@ public int getObjectPendingFinalizationCount() { return getIntAttribute(OBJECT_PENDING_FINALIZATION_COUNT); } - public long getGcCpuTime() { - throw new UnsupportedOperationException("This method is not supported"); - } - public boolean isVerbose() { return getBooleanAttribute(VERBOSE); } diff --git a/test/jdk/java/lang/management/MemoryMXBean/GetGcCpuTime.java b/test/jdk/com/sun/management/MemoryMXBean/GetTotalGcCpuTime.java similarity index 82% rename from test/jdk/java/lang/management/MemoryMXBean/GetGcCpuTime.java rename to test/jdk/com/sun/management/MemoryMXBean/GetTotalGcCpuTime.java index 1f73d6a04b6ac..7cfad08de9fc9 100644 --- a/test/jdk/java/lang/management/MemoryMXBean/GetGcCpuTime.java +++ b/test/jdk/com/sun/management/MemoryMXBean/GetTotalGcCpuTime.java @@ -25,29 +25,30 @@ * @test * @bug 8368527 * @library /test/lib - * @summary Stress MemoryMXBean.getGcCpuTime during shutdown + * @summary Stress MemoryMXBean.getTotalGcCpuTime during shutdown * - * @run main/othervm -XX:+UseSerialGC GetGcCpuTime _ - * @run main/othervm -XX:+UseParallelGC GetGcCpuTime _ - * @run main/othervm -XX:+UseG1GC GetGcCpuTime _ - * @run main/othervm -XX:+UseZGC GetGcCpuTime _ + * @run main/othervm -XX:+UseSerialGC GetTotalGcCpuTime _ + * @run main/othervm -XX:+UseParallelGC GetTotalGcCpuTime _ + * @run main/othervm -XX:+UseG1GC GetTotalGcCpuTime _ + * @run main/othervm -XX:+UseZGC GetTotalGcCpuTime _ */ import jdk.test.lib.process.OutputAnalyzer; import static jdk.test.lib.process.ProcessTools.createTestJavaProcessBuilder; import static jdk.test.lib.process.ProcessTools.executeProcess; +import com.sun.management.MemoryMXBean; + import java.lang.management.ManagementFactory; -import java.lang.management.MemoryMXBean; import java.lang.management.ThreadMXBean; -public class GetGcCpuTime { +public class GetTotalGcCpuTime { static final ThreadMXBean mxThreadBean = ManagementFactory.getThreadMXBean(); - static final MemoryMXBean mxMemoryBean = ManagementFactory.getMemoryMXBean(); + static final MemoryMXBean mxMemoryBean = ManagementFactory.getPlatformMXBean(MemoryMXBean.class); public static void main(String[] args) throws Exception { if (args.length > 0) { - ProcessBuilder pb = createTestJavaProcessBuilder("GetGcCpuTime"); + ProcessBuilder pb = createTestJavaProcessBuilder("GetTotalGcCpuTime"); OutputAnalyzer output = executeProcess(pb); output.shouldNotContain("GC CPU time should"); output.shouldHaveExitValue(0); @@ -59,7 +60,7 @@ public static void main(String[] args) throws Exception { return; } } catch (UnsupportedOperationException e) { - if (mxMemoryBean.getGcCpuTime() != -1) { + if (mxMemoryBean.getTotalGcCpuTime() != -1) { throw new Error("GC CPU time should be -1"); } return; @@ -69,7 +70,7 @@ public static void main(String[] args) throws Exception { for (int i = 0; i < numberOfThreads; i++) { Thread t = new Thread(() -> { while (true) { - long gcCpuTimeFromThread = mxMemoryBean.getGcCpuTime(); + long gcCpuTimeFromThread = mxMemoryBean.getTotalGcCpuTime(); if (gcCpuTimeFromThread < -1) { throw new Error("GC CPU time should never be less than -1 but was " + gcCpuTimeFromThread); } diff --git a/test/jdk/javax/management/mxbean/MXBeanInteropTest1.java b/test/jdk/javax/management/mxbean/MXBeanInteropTest1.java index 014b748b0d67f..500fef1c2f319 100644 --- a/test/jdk/javax/management/mxbean/MXBeanInteropTest1.java +++ b/test/jdk/javax/management/mxbean/MXBeanInteropTest1.java @@ -222,8 +222,6 @@ private final int doMemoryMXBeanTest(MBeanServerConnection mbsc) { + memory.getNonHeapMemoryUsage()); System.out.println("getObjectPendingFinalizationCount\t\t" + memory.getObjectPendingFinalizationCount()); - System.out.println("getGcCpuTime\t\t" - + memory.getGcCpuTime()); System.out.println("isVerbose\t\t" + memory.isVerbose()); From d046f4acc505c5c984c31a2b801a84aee8f31e9f Mon Sep 17 00:00:00 2001 From: Jonas Norlinder Date: Mon, 20 Oct 2025 13:52:22 +0200 Subject: [PATCH 04/14] Revert "Move from j.l.management to com.sun.management etc." This reverts commit 6431310109a02ec5c34f877a1c690afb00193043. --- src/hotspot/share/include/jmm.h | 4 +- .../java/lang/management/MemoryMXBean.java | 21 +++++++- .../classes/sun/management/MemoryImpl.java | 10 ++-- .../classes/sun/management/VMManagement.java | 2 +- .../sun/management/VMManagementImpl.java | 2 +- .../native/libmanagement/VMManagementImpl.c | 2 +- .../com/sun/management/MemoryMXBean.java | 53 ------------------- .../internal/HotSpotMemoryImpl.java | 43 --------------- .../internal/PlatformMBeanProviderImpl.java | 44 --------------- .../share/server/ServerMemoryMXBean.java | 4 ++ .../MemoryMXBean/GetGcCpuTime.java} | 23 ++++---- .../management/mxbean/MXBeanInteropTest1.java | 2 + 12 files changed, 48 insertions(+), 162 deletions(-) delete mode 100644 src/jdk.management/share/classes/com/sun/management/MemoryMXBean.java delete mode 100644 src/jdk.management/share/classes/com/sun/management/internal/HotSpotMemoryImpl.java rename test/jdk/{com/sun/management/MemoryMXBean/GetTotalGcCpuTime.java => java/lang/management/MemoryMXBean/GetGcCpuTime.java} (82%) diff --git a/src/hotspot/share/include/jmm.h b/src/hotspot/share/include/jmm.h index efe4aef0229a9..60b04daef7f25 100644 --- a/src/hotspot/share/include/jmm.h +++ b/src/hotspot/share/include/jmm.h @@ -81,8 +81,8 @@ typedef enum { JMM_COMPILE_TOTAL_TIME_MS = 8, /* Total accumulated time spent in compilation */ JMM_GC_TIME_MS = 9, /* Total accumulated time spent in collection */ JMM_GC_COUNT = 10, /* Total number of collections */ - JMM_JVM_UPTIME_MS = 11, /* The JVM uptime in milliseconds */ - JMM_GC_CPU_TIME = 12, /* Total accumulated GC CPU time */ + JMM_GC_CPU_TIME = 11, /* Total accumulated GC CPU time */ + JMM_JVM_UPTIME_MS = 12, /* The JVM uptime in milliseconds */ JMM_INTERNAL_ATTRIBUTE_INDEX = 100, JMM_CLASS_LOADED_BYTES = 101, /* Number of bytes loaded instance classes */ diff --git a/src/java.management/share/classes/java/lang/management/MemoryMXBean.java b/src/java.management/share/classes/java/lang/management/MemoryMXBean.java index 2c982e1ce9c67..71bb4a67b1347 100644 --- a/src/java.management/share/classes/java/lang/management/MemoryMXBean.java +++ b/src/java.management/share/classes/java/lang/management/MemoryMXBean.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, 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 @@ -267,6 +267,24 @@ public interface MemoryMXBean extends PlatformManagedObject { */ public MemoryUsage getNonHeapMemoryUsage(); + /** + * Returns the CPU time used by all garbage collection threads. + * + *

This include time since genesis, so the value can be + * non-zero even if no garbage collection cycles occured. In + * general this includes time for all driver threads, + * workers, VM operations on the VM thread and the string + * deduplication thread (if enabled). This method returns + * {@code -1} if the platform does not support this operation + * or if called during shutdown. + * + * @return the total CPU time for all garbage collection + * threads in nanoseconds. + * + * @since 26 + */ + public long getGcCpuTime(); + /** * Tests if verbose output for the memory system is enabled. * @@ -302,5 +320,4 @@ public interface MemoryMXBean extends PlatformManagedObject { * @see java.lang.System#gc() */ public void gc(); - } diff --git a/src/java.management/share/classes/sun/management/MemoryImpl.java b/src/java.management/share/classes/sun/management/MemoryImpl.java index bc481acfe83bf..748a36c5434d3 100644 --- a/src/java.management/share/classes/sun/management/MemoryImpl.java +++ b/src/java.management/share/classes/sun/management/MemoryImpl.java @@ -43,10 +43,10 @@ * ManagementFactory.getMemoryMXBean() returns an instance * of this class. */ -public class MemoryImpl extends NotificationEmitterSupport +class MemoryImpl extends NotificationEmitterSupport implements MemoryMXBean { - protected final VMManagement jvm; + private final VMManagement jvm; private static MemoryPoolMXBean[] pools = null; private static MemoryManagerMXBean[] mgrs = null; @@ -54,7 +54,7 @@ public class MemoryImpl extends NotificationEmitterSupport /** * Constructor of MemoryImpl class */ - protected MemoryImpl(VMManagement vm) { + MemoryImpl(VMManagement vm) { this.jvm = vm; } @@ -67,6 +67,10 @@ public void gc() { Runtime.getRuntime().gc(); } + public long getGcCpuTime() { + return jvm.getGcCpuTime(); + } + // Need to make a VM call to get coherent value public MemoryUsage getHeapMemoryUsage() { return getMemoryUsage0(true); diff --git a/src/java.management/share/classes/sun/management/VMManagement.java b/src/java.management/share/classes/sun/management/VMManagement.java index 3e227225ccd65..3d1af88666274 100644 --- a/src/java.management/share/classes/sun/management/VMManagement.java +++ b/src/java.management/share/classes/sun/management/VMManagement.java @@ -55,7 +55,7 @@ public interface VMManagement { public boolean getVerboseClass(); // Memory Subsystem - public long getTotalGcCpuTime(); + public long getGcCpuTime(); public boolean getVerboseGC(); // Runtime Subsystem diff --git a/src/java.management/share/classes/sun/management/VMManagementImpl.java b/src/java.management/share/classes/sun/management/VMManagementImpl.java index b8c7a2921d477..7ede618b2f21e 100644 --- a/src/java.management/share/classes/sun/management/VMManagementImpl.java +++ b/src/java.management/share/classes/sun/management/VMManagementImpl.java @@ -128,7 +128,7 @@ public int getLoadedClassCount() { public native boolean getVerboseClass(); // Memory Subsystem - public native long getTotalGcCpuTime(); + public native long getGcCpuTime(); public native boolean getVerboseGC(); // Runtime Subsystem diff --git a/src/java.management/share/native/libmanagement/VMManagementImpl.c b/src/java.management/share/native/libmanagement/VMManagementImpl.c index f7cedff03a4e4..b4ae7aca8e200 100644 --- a/src/java.management/share/native/libmanagement/VMManagementImpl.c +++ b/src/java.management/share/native/libmanagement/VMManagementImpl.c @@ -122,7 +122,7 @@ Java_sun_management_VMManagementImpl_getUnloadedClassCount } JNIEXPORT jlong JNICALL -Java_sun_management_VMManagementImpl_getTotalGcCpuTime +Java_sun_management_VMManagementImpl_getGcCpuTime (JNIEnv *env, jobject dummy) { return jmm_interface->GetLongAttribute(env, NULL, JMM_GC_CPU_TIME); diff --git a/src/jdk.management/share/classes/com/sun/management/MemoryMXBean.java b/src/jdk.management/share/classes/com/sun/management/MemoryMXBean.java deleted file mode 100644 index 5444d7e8e0f5c..0000000000000 --- a/src/jdk.management/share/classes/com/sun/management/MemoryMXBean.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2025, 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 - * 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.sun.management; - -/** - * Platform-specific management interface for the memory - * system on which the Java virtual machine is running. - * - * @since 26 - */ - -public interface MemoryMXBean extends java.lang.management.MemoryMXBean { - /** - * Returns the CPU time used by garbage collection. - * - *

CPU time used by all garbage collection. In - * general this includes time for all driver threads, - * workers, VM operations on the VM thread and the string - * deduplication thread (if enabled). May be non-zero even if no - * GC cycle occurred. This method returns {@code -1} if the - * platform does not support this operation or if called during - * shutdown. - * - * @return the total accumulated CPU time for garbage collection - * in nanoseconds. - * - * @since 26 - */ - public long getTotalGcCpuTime(); -} diff --git a/src/jdk.management/share/classes/com/sun/management/internal/HotSpotMemoryImpl.java b/src/jdk.management/share/classes/com/sun/management/internal/HotSpotMemoryImpl.java deleted file mode 100644 index 64d072eb4ce58..0000000000000 --- a/src/jdk.management/share/classes/com/sun/management/internal/HotSpotMemoryImpl.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2025, 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 - * 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.sun.management.internal; - -import com.sun.management.MemoryMXBean; -import sun.management.ManagementFactoryHelper; -import sun.management.MemoryImpl; -import sun.management.VMManagement; - -/** - * Implementation of the Memory MBean for Hotspot VM. - */ -public class HotSpotMemoryImpl extends MemoryImpl implements MemoryMXBean { - public HotSpotMemoryImpl(VMManagement vm) { - super(ManagementFactoryHelper.getVMManagement()); - } - - public long getTotalGcCpuTime() { - return jvm.getTotalGcCpuTime(); - } -} diff --git a/src/jdk.management/share/classes/com/sun/management/internal/PlatformMBeanProviderImpl.java b/src/jdk.management/share/classes/com/sun/management/internal/PlatformMBeanProviderImpl.java index 9e903f2b87106..3a64fe6b858fe 100644 --- a/src/jdk.management/share/classes/com/sun/management/internal/PlatformMBeanProviderImpl.java +++ b/src/jdk.management/share/classes/com/sun/management/internal/PlatformMBeanProviderImpl.java @@ -29,7 +29,6 @@ import com.sun.management.ThreadMXBean; import java.lang.management.ManagementFactory; import java.lang.management.MemoryManagerMXBean; -import java.lang.management.MemoryMXBean; import java.lang.management.OperatingSystemMXBean; import java.util.ArrayList; import java.util.Collections; @@ -52,7 +51,6 @@ public final class PlatformMBeanProviderImpl extends PlatformMBeanProvider { private final List> mxbeanList; private static HotSpotDiagnostic hsDiagMBean = null; private static OperatingSystemMXBean osMBean = null; - private static MemoryMXBean memoryMBean = null; static { System.loadLibrary("management_ext"); @@ -196,41 +194,6 @@ public Map nameToMBeanMap() { } }); - /** - * MemoryMXBean - */ - initMBeanList.add(new PlatformComponent() { - private final Set memoryMXBeanInterfaceNames - = Collections.unmodifiableSet( - Stream.of("java.lang.management.MemoryMXBean", - "com.sun.management.MemoryMXBean") - .collect(Collectors.toSet())); - - @Override - public Set> mbeanInterfaces() { - return Stream.of(java.lang.management.MemoryMXBean.class, - com.sun.management.MemoryMXBean.class) - .collect(Collectors.toSet()); - } - - @Override - public Set mbeanInterfaceNames() { - return memoryMXBeanInterfaceNames; - } - - @Override - public String getObjectNamePattern() { - return ManagementFactory.MEMORY_MXBEAN_NAME; - } - - @Override - public Map nameToMBeanMap() { - return Collections.singletonMap( - ManagementFactory.MEMORY_MXBEAN_NAME, - getMemoryMXBean()); - } - }); - /** * OperatingSystemMXBean */ @@ -349,11 +312,4 @@ private static synchronized OperatingSystemMXBean getOperatingSystemMXBean() { } return osMBean; } - - private static synchronized MemoryMXBean getMemoryMXBean() { - if (memoryMBean == null) { - memoryMBean = new HotSpotMemoryImpl(ManagementFactoryHelper.getVMManagement()); - } - return memoryMBean; - } } diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/share/server/ServerMemoryMXBean.java b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/share/server/ServerMemoryMXBean.java index 0c536fcd12367..fa4c43ac5735d 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/share/server/ServerMemoryMXBean.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/share/server/ServerMemoryMXBean.java @@ -58,6 +58,10 @@ public int getObjectPendingFinalizationCount() { return getIntAttribute(OBJECT_PENDING_FINALIZATION_COUNT); } + public long getGcCpuTime() { + throw new UnsupportedOperationException("This method is not supported"); + } + public boolean isVerbose() { return getBooleanAttribute(VERBOSE); } diff --git a/test/jdk/com/sun/management/MemoryMXBean/GetTotalGcCpuTime.java b/test/jdk/java/lang/management/MemoryMXBean/GetGcCpuTime.java similarity index 82% rename from test/jdk/com/sun/management/MemoryMXBean/GetTotalGcCpuTime.java rename to test/jdk/java/lang/management/MemoryMXBean/GetGcCpuTime.java index 7cfad08de9fc9..1f73d6a04b6ac 100644 --- a/test/jdk/com/sun/management/MemoryMXBean/GetTotalGcCpuTime.java +++ b/test/jdk/java/lang/management/MemoryMXBean/GetGcCpuTime.java @@ -25,30 +25,29 @@ * @test * @bug 8368527 * @library /test/lib - * @summary Stress MemoryMXBean.getTotalGcCpuTime during shutdown + * @summary Stress MemoryMXBean.getGcCpuTime during shutdown * - * @run main/othervm -XX:+UseSerialGC GetTotalGcCpuTime _ - * @run main/othervm -XX:+UseParallelGC GetTotalGcCpuTime _ - * @run main/othervm -XX:+UseG1GC GetTotalGcCpuTime _ - * @run main/othervm -XX:+UseZGC GetTotalGcCpuTime _ + * @run main/othervm -XX:+UseSerialGC GetGcCpuTime _ + * @run main/othervm -XX:+UseParallelGC GetGcCpuTime _ + * @run main/othervm -XX:+UseG1GC GetGcCpuTime _ + * @run main/othervm -XX:+UseZGC GetGcCpuTime _ */ import jdk.test.lib.process.OutputAnalyzer; import static jdk.test.lib.process.ProcessTools.createTestJavaProcessBuilder; import static jdk.test.lib.process.ProcessTools.executeProcess; -import com.sun.management.MemoryMXBean; - import java.lang.management.ManagementFactory; +import java.lang.management.MemoryMXBean; import java.lang.management.ThreadMXBean; -public class GetTotalGcCpuTime { +public class GetGcCpuTime { static final ThreadMXBean mxThreadBean = ManagementFactory.getThreadMXBean(); - static final MemoryMXBean mxMemoryBean = ManagementFactory.getPlatformMXBean(MemoryMXBean.class); + static final MemoryMXBean mxMemoryBean = ManagementFactory.getMemoryMXBean(); public static void main(String[] args) throws Exception { if (args.length > 0) { - ProcessBuilder pb = createTestJavaProcessBuilder("GetTotalGcCpuTime"); + ProcessBuilder pb = createTestJavaProcessBuilder("GetGcCpuTime"); OutputAnalyzer output = executeProcess(pb); output.shouldNotContain("GC CPU time should"); output.shouldHaveExitValue(0); @@ -60,7 +59,7 @@ public static void main(String[] args) throws Exception { return; } } catch (UnsupportedOperationException e) { - if (mxMemoryBean.getTotalGcCpuTime() != -1) { + if (mxMemoryBean.getGcCpuTime() != -1) { throw new Error("GC CPU time should be -1"); } return; @@ -70,7 +69,7 @@ public static void main(String[] args) throws Exception { for (int i = 0; i < numberOfThreads; i++) { Thread t = new Thread(() -> { while (true) { - long gcCpuTimeFromThread = mxMemoryBean.getTotalGcCpuTime(); + long gcCpuTimeFromThread = mxMemoryBean.getGcCpuTime(); if (gcCpuTimeFromThread < -1) { throw new Error("GC CPU time should never be less than -1 but was " + gcCpuTimeFromThread); } diff --git a/test/jdk/javax/management/mxbean/MXBeanInteropTest1.java b/test/jdk/javax/management/mxbean/MXBeanInteropTest1.java index 500fef1c2f319..014b748b0d67f 100644 --- a/test/jdk/javax/management/mxbean/MXBeanInteropTest1.java +++ b/test/jdk/javax/management/mxbean/MXBeanInteropTest1.java @@ -222,6 +222,8 @@ private final int doMemoryMXBeanTest(MBeanServerConnection mbsc) { + memory.getNonHeapMemoryUsage()); System.out.println("getObjectPendingFinalizationCount\t\t" + memory.getObjectPendingFinalizationCount()); + System.out.println("getGcCpuTime\t\t" + + memory.getGcCpuTime()); System.out.println("isVerbose\t\t" + memory.isVerbose()); From b03db63e30eb2276ce248fbbf360a7ffb9bfe265 Mon Sep 17 00:00:00 2001 From: Jonas Norlinder Date: Mon, 20 Oct 2025 19:32:47 +0200 Subject: [PATCH 05/14] j.l.management with generic API docs --- src/hotspot/share/include/jmm.h | 4 +-- src/hotspot/share/services/management.cpp | 2 +- .../java/lang/management/MemoryMXBean.java | 28 +++++++++++-------- .../classes/sun/management/MemoryImpl.java | 4 +-- .../classes/sun/management/VMManagement.java | 2 +- .../sun/management/VMManagementImpl.java | 2 +- .../native/libmanagement/VMManagementImpl.c | 4 +-- .../share/server/ServerMemoryMXBean.java | 2 +- ...tGcCpuTime.java => GetTotalGcCpuTime.java} | 18 ++++++------ .../management/mxbean/MXBeanInteropTest1.java | 4 +-- 10 files changed, 38 insertions(+), 32 deletions(-) rename test/jdk/java/lang/management/MemoryMXBean/{GetGcCpuTime.java => GetTotalGcCpuTime.java} (84%) diff --git a/src/hotspot/share/include/jmm.h b/src/hotspot/share/include/jmm.h index 60b04daef7f25..ee1462fe5a83e 100644 --- a/src/hotspot/share/include/jmm.h +++ b/src/hotspot/share/include/jmm.h @@ -81,8 +81,8 @@ typedef enum { JMM_COMPILE_TOTAL_TIME_MS = 8, /* Total accumulated time spent in compilation */ JMM_GC_TIME_MS = 9, /* Total accumulated time spent in collection */ JMM_GC_COUNT = 10, /* Total number of collections */ - JMM_GC_CPU_TIME = 11, /* Total accumulated GC CPU time */ - JMM_JVM_UPTIME_MS = 12, /* The JVM uptime in milliseconds */ + JMM_JVM_UPTIME_MS = 11, /* The JVM uptime in milliseconds */ + JMM_TOTAL_GC_CPU_TIME = 12, /* Total accumulated GC CPU time */ JMM_INTERNAL_ATTRIBUTE_INDEX = 100, JMM_CLASS_LOADED_BYTES = 101, /* Number of bytes loaded instance classes */ diff --git a/src/hotspot/share/services/management.cpp b/src/hotspot/share/services/management.cpp index 11a3e2ef75c3e..cc26e2e135256 100644 --- a/src/hotspot/share/services/management.cpp +++ b/src/hotspot/share/services/management.cpp @@ -931,7 +931,7 @@ static jlong get_long_attribute(jmmLongAttribute att) { case JMM_JVM_UPTIME_MS: return Management::ticks_to_ms(os::elapsed_counter()); - case JMM_GC_CPU_TIME: + case JMM_TOTAL_GC_CPU_TIME: return get_gc_cpu_time(); case JMM_COMPILE_TOTAL_TIME_MS: diff --git a/src/java.management/share/classes/java/lang/management/MemoryMXBean.java b/src/java.management/share/classes/java/lang/management/MemoryMXBean.java index 71bb4a67b1347..2ea09eb24befa 100644 --- a/src/java.management/share/classes/java/lang/management/MemoryMXBean.java +++ b/src/java.management/share/classes/java/lang/management/MemoryMXBean.java @@ -268,22 +268,28 @@ public interface MemoryMXBean extends PlatformManagedObject { public MemoryUsage getNonHeapMemoryUsage(); /** - * Returns the CPU time used by all garbage collection threads. + * Returns the CPU time used by garbage collection. * - *

This include time since genesis, so the value can be - * non-zero even if no garbage collection cycles occured. In - * general this includes time for all driver threads, - * workers, VM operations on the VM thread and the string - * deduplication thread (if enabled). This method returns - * {@code -1} if the platform does not support this operation - * or if called during shutdown. + *

This is the CPU time used by all garbage collection + * activity, including any overhead, which means the result + * may be non-zero even if no GC has occurred. + * + * This method return {@code -1} if the platform does + * not support this operation or the information is not + * available. + * + * @implNote Reported time will include relevant + * implementation-specific details such as driver threads, + * workers, VM Operations and string deduplication (if enabled). + * The return value can be -1 if called when measurement is + * not possible, such as during shutdown. * - * @return the total CPU time for all garbage collection - * threads in nanoseconds. + * @return the total accumulated CPU time for garbage collection + * in nanoseconds, or -1 * * @since 26 */ - public long getGcCpuTime(); + public long getTotalGcCpuTime(); /** * Tests if verbose output for the memory system is enabled. diff --git a/src/java.management/share/classes/sun/management/MemoryImpl.java b/src/java.management/share/classes/sun/management/MemoryImpl.java index 748a36c5434d3..3e27ba2e5bb18 100644 --- a/src/java.management/share/classes/sun/management/MemoryImpl.java +++ b/src/java.management/share/classes/sun/management/MemoryImpl.java @@ -67,8 +67,8 @@ public void gc() { Runtime.getRuntime().gc(); } - public long getGcCpuTime() { - return jvm.getGcCpuTime(); + public long getTotalGcCpuTime() { + return jvm.getTotalGcCpuTime(); } // Need to make a VM call to get coherent value diff --git a/src/java.management/share/classes/sun/management/VMManagement.java b/src/java.management/share/classes/sun/management/VMManagement.java index 3d1af88666274..3e227225ccd65 100644 --- a/src/java.management/share/classes/sun/management/VMManagement.java +++ b/src/java.management/share/classes/sun/management/VMManagement.java @@ -55,7 +55,7 @@ public interface VMManagement { public boolean getVerboseClass(); // Memory Subsystem - public long getGcCpuTime(); + public long getTotalGcCpuTime(); public boolean getVerboseGC(); // Runtime Subsystem diff --git a/src/java.management/share/classes/sun/management/VMManagementImpl.java b/src/java.management/share/classes/sun/management/VMManagementImpl.java index 7ede618b2f21e..b8c7a2921d477 100644 --- a/src/java.management/share/classes/sun/management/VMManagementImpl.java +++ b/src/java.management/share/classes/sun/management/VMManagementImpl.java @@ -128,7 +128,7 @@ public int getLoadedClassCount() { public native boolean getVerboseClass(); // Memory Subsystem - public native long getGcCpuTime(); + public native long getTotalGcCpuTime(); public native boolean getVerboseGC(); // Runtime Subsystem diff --git a/src/java.management/share/native/libmanagement/VMManagementImpl.c b/src/java.management/share/native/libmanagement/VMManagementImpl.c index b4ae7aca8e200..d5141c71ee798 100644 --- a/src/java.management/share/native/libmanagement/VMManagementImpl.c +++ b/src/java.management/share/native/libmanagement/VMManagementImpl.c @@ -122,10 +122,10 @@ Java_sun_management_VMManagementImpl_getUnloadedClassCount } JNIEXPORT jlong JNICALL -Java_sun_management_VMManagementImpl_getGcCpuTime +Java_sun_management_VMManagementImpl_getTotalGcCpuTime (JNIEnv *env, jobject dummy) { - return jmm_interface->GetLongAttribute(env, NULL, JMM_GC_CPU_TIME); + return jmm_interface->GetLongAttribute(env, NULL, JMM_TOTAL_GC_CPU_TIME); } JNIEXPORT jboolean JNICALL diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/share/server/ServerMemoryMXBean.java b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/share/server/ServerMemoryMXBean.java index fa4c43ac5735d..31050b6b8bb66 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/share/server/ServerMemoryMXBean.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/share/server/ServerMemoryMXBean.java @@ -58,7 +58,7 @@ public int getObjectPendingFinalizationCount() { return getIntAttribute(OBJECT_PENDING_FINALIZATION_COUNT); } - public long getGcCpuTime() { + public long getTotalGcCpuTime() { throw new UnsupportedOperationException("This method is not supported"); } diff --git a/test/jdk/java/lang/management/MemoryMXBean/GetGcCpuTime.java b/test/jdk/java/lang/management/MemoryMXBean/GetTotalGcCpuTime.java similarity index 84% rename from test/jdk/java/lang/management/MemoryMXBean/GetGcCpuTime.java rename to test/jdk/java/lang/management/MemoryMXBean/GetTotalGcCpuTime.java index 1f73d6a04b6ac..a0feef0bb15ba 100644 --- a/test/jdk/java/lang/management/MemoryMXBean/GetGcCpuTime.java +++ b/test/jdk/java/lang/management/MemoryMXBean/GetTotalGcCpuTime.java @@ -25,12 +25,12 @@ * @test * @bug 8368527 * @library /test/lib - * @summary Stress MemoryMXBean.getGcCpuTime during shutdown + * @summary Stress MemoryMXBean.getTotalGcCpuTime during shutdown * - * @run main/othervm -XX:+UseSerialGC GetGcCpuTime _ - * @run main/othervm -XX:+UseParallelGC GetGcCpuTime _ - * @run main/othervm -XX:+UseG1GC GetGcCpuTime _ - * @run main/othervm -XX:+UseZGC GetGcCpuTime _ + * @run main/othervm -XX:+UseSerialGC GetTotalGcCpuTime _ + * @run main/othervm -XX:+UseParallelGC GetTotalGcCpuTime _ + * @run main/othervm -XX:+UseG1GC GetTotalGcCpuTime _ + * @run main/othervm -XX:+UseZGC GetTotalGcCpuTime _ */ import jdk.test.lib.process.OutputAnalyzer; @@ -41,13 +41,13 @@ import java.lang.management.MemoryMXBean; import java.lang.management.ThreadMXBean; -public class GetGcCpuTime { +public class GetTotalGcCpuTime { static final ThreadMXBean mxThreadBean = ManagementFactory.getThreadMXBean(); static final MemoryMXBean mxMemoryBean = ManagementFactory.getMemoryMXBean(); public static void main(String[] args) throws Exception { if (args.length > 0) { - ProcessBuilder pb = createTestJavaProcessBuilder("GetGcCpuTime"); + ProcessBuilder pb = createTestJavaProcessBuilder("GetTotalGcCpuTime"); OutputAnalyzer output = executeProcess(pb); output.shouldNotContain("GC CPU time should"); output.shouldHaveExitValue(0); @@ -59,7 +59,7 @@ public static void main(String[] args) throws Exception { return; } } catch (UnsupportedOperationException e) { - if (mxMemoryBean.getGcCpuTime() != -1) { + if (mxMemoryBean.getTotalGcCpuTime() != -1) { throw new Error("GC CPU time should be -1"); } return; @@ -69,7 +69,7 @@ public static void main(String[] args) throws Exception { for (int i = 0; i < numberOfThreads; i++) { Thread t = new Thread(() -> { while (true) { - long gcCpuTimeFromThread = mxMemoryBean.getGcCpuTime(); + long gcCpuTimeFromThread = mxMemoryBean.getTotalGcCpuTime(); if (gcCpuTimeFromThread < -1) { throw new Error("GC CPU time should never be less than -1 but was " + gcCpuTimeFromThread); } diff --git a/test/jdk/javax/management/mxbean/MXBeanInteropTest1.java b/test/jdk/javax/management/mxbean/MXBeanInteropTest1.java index 014b748b0d67f..011bdb144fb36 100644 --- a/test/jdk/javax/management/mxbean/MXBeanInteropTest1.java +++ b/test/jdk/javax/management/mxbean/MXBeanInteropTest1.java @@ -222,8 +222,8 @@ private final int doMemoryMXBeanTest(MBeanServerConnection mbsc) { + memory.getNonHeapMemoryUsage()); System.out.println("getObjectPendingFinalizationCount\t\t" + memory.getObjectPendingFinalizationCount()); - System.out.println("getGcCpuTime\t\t" - + memory.getGcCpuTime()); + System.out.println("getTotalGcCpuTime\t\t" + + memory.getTotalGcCpuTime()); System.out.println("isVerbose\t\t" + memory.isVerbose()); From 8d83dd97d5addfa7cb2f49c61a3942de13dcc54b Mon Sep 17 00:00:00 2001 From: Jonas Norlinder Date: Mon, 20 Oct 2025 19:37:58 +0200 Subject: [PATCH 06/14] Remove tabs --- .../classes/java/lang/management/MemoryMXBean.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/java.management/share/classes/java/lang/management/MemoryMXBean.java b/src/java.management/share/classes/java/lang/management/MemoryMXBean.java index 2ea09eb24befa..81646bae9c19a 100644 --- a/src/java.management/share/classes/java/lang/management/MemoryMXBean.java +++ b/src/java.management/share/classes/java/lang/management/MemoryMXBean.java @@ -273,18 +273,18 @@ public interface MemoryMXBean extends PlatformManagedObject { *

This is the CPU time used by all garbage collection * activity, including any overhead, which means the result * may be non-zero even if no GC has occurred. - * - * This method return {@code -1} if the platform does + * + * This method return {@code -1} if the platform does * not support this operation or the information is not * available. - * + * * @implNote Reported time will include relevant * implementation-specific details such as driver threads, * workers, VM Operations and string deduplication (if enabled). - * The return value can be -1 if called when measurement is + * The return value can be -1 if called when measurement is * not possible, such as during shutdown. * - * @return the total accumulated CPU time for garbage collection + * @return the total accumulated CPU time for garbage collection * in nanoseconds, or -1 * * @since 26 From a188df0bdf9c2848b648f5c40f2fba6ee9bb944e Mon Sep 17 00:00:00 2001 From: Jonas Norlinder Date: Wed, 22 Oct 2025 13:23:15 +0200 Subject: [PATCH 07/14] Fix typo --- .../share/classes/java/lang/management/MemoryMXBean.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/java.management/share/classes/java/lang/management/MemoryMXBean.java b/src/java.management/share/classes/java/lang/management/MemoryMXBean.java index 81646bae9c19a..fb7792b09ac54 100644 --- a/src/java.management/share/classes/java/lang/management/MemoryMXBean.java +++ b/src/java.management/share/classes/java/lang/management/MemoryMXBean.java @@ -274,7 +274,7 @@ public interface MemoryMXBean extends PlatformManagedObject { * activity, including any overhead, which means the result * may be non-zero even if no GC has occurred. * - * This method return {@code -1} if the platform does + * This method returns {@code -1} if the platform does * not support this operation or the information is not * available. * From f8a9f7a38d00d4c3a79898e100541387a23cb147 Mon Sep 17 00:00:00 2001 From: Jonas Norlinder Date: Fri, 24 Oct 2025 14:15:26 +0200 Subject: [PATCH 08/14] Add default implementation and elaborate API docs --- .../java/lang/management/MemoryMXBean.java | 28 +++++++++++++------ 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/src/java.management/share/classes/java/lang/management/MemoryMXBean.java b/src/java.management/share/classes/java/lang/management/MemoryMXBean.java index fb7792b09ac54..72eb97cda9614 100644 --- a/src/java.management/share/classes/java/lang/management/MemoryMXBean.java +++ b/src/java.management/share/classes/java/lang/management/MemoryMXBean.java @@ -268,7 +268,8 @@ public interface MemoryMXBean extends PlatformManagedObject { public MemoryUsage getNonHeapMemoryUsage(); /** - * Returns the CPU time used by garbage collection. + * Returns the approximate accumulated time, in nanoseconds, + * spent in garbage collection. * *

This is the CPU time used by all garbage collection * activity, including any overhead, which means the result @@ -278,18 +279,29 @@ public interface MemoryMXBean extends PlatformManagedObject { * not support this operation or the information is not * available. * - * @implNote Reported time will include relevant - * implementation-specific details such as driver threads, - * workers, VM Operations and string deduplication (if enabled). - * The return value can be -1 if called when measurement is - * not possible, such as during shutdown. + * @apiNote + * May be used in conjunction with com.sun.management.OperatingSystemMXBean.getProcessCpuTime() + * for calculating the GC's usage of CPU time as a whole. + * + * @implNote The specifics on what constitutes the time spent + * in garbage collection is highly implementation dependent. + * In the HotSpot Virtual Machine implementation reported + * time will include relevant implementation-specific details such + * as driver threads, workers, VM Operations and string + * deduplication (if enabled). Driver threads may be created by a GC + * to orchestrate its work. The return value can be -1 if + * called when measurement is not possible, such as during shutdown. + * + * @implSpec The default implementation return {@code -1}. * * @return the total accumulated CPU time for garbage collection - * in nanoseconds, or -1 + * in nanoseconds, or {@code -1}. * * @since 26 */ - public long getTotalGcCpuTime(); + default public long getTotalGcCpuTime() { + return -1; + }; /** * Tests if verbose output for the memory system is enabled. From 08af7b516cde9ac7aee241fe67351d7f8bd011ff Mon Sep 17 00:00:00 2001 From: Jonas Norlinder Date: Fri, 24 Oct 2025 14:31:30 +0200 Subject: [PATCH 09/14] Fix link for getProcessCpuTime --- .../share/classes/java/lang/management/MemoryMXBean.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/java.management/share/classes/java/lang/management/MemoryMXBean.java b/src/java.management/share/classes/java/lang/management/MemoryMXBean.java index 72eb97cda9614..8ae6720031953 100644 --- a/src/java.management/share/classes/java/lang/management/MemoryMXBean.java +++ b/src/java.management/share/classes/java/lang/management/MemoryMXBean.java @@ -280,7 +280,7 @@ public interface MemoryMXBean extends PlatformManagedObject { * available. * * @apiNote - * May be used in conjunction with com.sun.management.OperatingSystemMXBean.getProcessCpuTime() + * May be used in conjunction with {@link jdk.management/com.sun.management.OperatingSystemMXBean#getProcessCpuTime()} * for calculating the GC's usage of CPU time as a whole. * * @implNote The specifics on what constitutes the time spent @@ -299,6 +299,7 @@ public interface MemoryMXBean extends PlatformManagedObject { * * @since 26 */ + @SuppressWarnings("doclint:reference") default public long getTotalGcCpuTime() { return -1; }; From 5d360f453e6f9847d2baf88843dd05f269c32c0f Mon Sep 17 00:00:00 2001 From: Jonas Norlinder Date: Fri, 24 Oct 2025 20:22:08 +0200 Subject: [PATCH 10/14] Review fixes --- .../java/lang/management/MemoryMXBean.java | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/java.management/share/classes/java/lang/management/MemoryMXBean.java b/src/java.management/share/classes/java/lang/management/MemoryMXBean.java index 8ae6720031953..9f3a33c416843 100644 --- a/src/java.management/share/classes/java/lang/management/MemoryMXBean.java +++ b/src/java.management/share/classes/java/lang/management/MemoryMXBean.java @@ -269,11 +269,11 @@ public interface MemoryMXBean extends PlatformManagedObject { /** * Returns the approximate accumulated time, in nanoseconds, - * spent in garbage collection. + * spent in garbage collection (GC). * - *

This is the CPU time used by all garbage collection - * activity, including any overhead, which means the result - * may be non-zero even if no GC has occurred. + *

The time spent in spent in GC is the CPU time used by + * all GC activity, including any overhead, which means the + * result may be non-zero even if no GC has occurred. * * This method returns {@code -1} if the platform does * not support this operation or the information is not @@ -283,19 +283,19 @@ public interface MemoryMXBean extends PlatformManagedObject { * May be used in conjunction with {@link jdk.management/com.sun.management.OperatingSystemMXBean#getProcessCpuTime()} * for calculating the GC's usage of CPU time as a whole. * - * @implNote The specifics on what constitutes the time spent - * in garbage collection is highly implementation dependent. - * In the HotSpot Virtual Machine implementation reported - * time will include relevant implementation-specific details such - * as driver threads, workers, VM Operations and string - * deduplication (if enabled). Driver threads may be created by a GC - * to orchestrate its work. The return value can be -1 if - * called when measurement is not possible, such as during shutdown. + * @implNote The specifics on what constitutes the time spent + * in GC is highly implementation dependent. In the HotSpot + * Virtual Machine, this time includes relevant + * implementation-specific details such as driver threads, + * workers, VM Operations and string deduplication (if + * enabled). Driver threads may be created by a GC to + * orchestrate its work. The return value can be -1 if called + * when measurement is not possible, such as during shutdown. * * @implSpec The default implementation return {@code -1}. * - * @return the total accumulated CPU time for garbage collection - * in nanoseconds, or {@code -1}. + * @return the total accumulated CPU time for GC in + * nanoseconds, or {@code -1}. * * @since 26 */ From 5960a1d6fd6dccf756ad497a7cfa7c1549870af8 Mon Sep 17 00:00:00 2001 From: Jonas Norlinder Date: Sun, 26 Oct 2025 21:05:14 +0100 Subject: [PATCH 11/14] Change how test is invoked and fix review comment --- .../java/lang/management/MemoryMXBean.java | 2 +- ...tressGetTotalGcCpuTimeDuringShutdown.java} | 55 +++++++++++-------- 2 files changed, 34 insertions(+), 23 deletions(-) rename test/jdk/java/lang/management/MemoryMXBean/{GetTotalGcCpuTime.java => StressGetTotalGcCpuTimeDuringShutdown.java} (66%) diff --git a/src/java.management/share/classes/java/lang/management/MemoryMXBean.java b/src/java.management/share/classes/java/lang/management/MemoryMXBean.java index 9f3a33c416843..edd079e2faac5 100644 --- a/src/java.management/share/classes/java/lang/management/MemoryMXBean.java +++ b/src/java.management/share/classes/java/lang/management/MemoryMXBean.java @@ -302,7 +302,7 @@ public interface MemoryMXBean extends PlatformManagedObject { @SuppressWarnings("doclint:reference") default public long getTotalGcCpuTime() { return -1; - }; + } /** * Tests if verbose output for the memory system is enabled. diff --git a/test/jdk/java/lang/management/MemoryMXBean/GetTotalGcCpuTime.java b/test/jdk/java/lang/management/MemoryMXBean/StressGetTotalGcCpuTimeDuringShutdown.java similarity index 66% rename from test/jdk/java/lang/management/MemoryMXBean/GetTotalGcCpuTime.java rename to test/jdk/java/lang/management/MemoryMXBean/StressGetTotalGcCpuTimeDuringShutdown.java index a0feef0bb15ba..cba74e1b554b7 100644 --- a/test/jdk/java/lang/management/MemoryMXBean/GetTotalGcCpuTime.java +++ b/test/jdk/java/lang/management/MemoryMXBean/StressGetTotalGcCpuTimeDuringShutdown.java @@ -22,45 +22,57 @@ */ /* - * @test + * @test id=Parallel + * @requires vm.gc.Parallel * @bug 8368527 + * @summary Stress MemoryMXBean.getTotalGcCpuTime during shutdown * @library /test/lib + * @run main/othervm -XX:+UseParallelGC StressGetTotalGcCpuTimeDuringShutdown + */ + +/* + * @test id=G1 + * @requires vm.gc.G1 + * @bug 8368527 * @summary Stress MemoryMXBean.getTotalGcCpuTime during shutdown - * - * @run main/othervm -XX:+UseSerialGC GetTotalGcCpuTime _ - * @run main/othervm -XX:+UseParallelGC GetTotalGcCpuTime _ - * @run main/othervm -XX:+UseG1GC GetTotalGcCpuTime _ - * @run main/othervm -XX:+UseZGC GetTotalGcCpuTime _ + * @library /test/lib + * @run main/othervm -XX:+UseG1GC StressGetTotalGcCpuTimeDuringShutdown + */ + +/* + * @test id=ZGC + * @requires vm.gc.Z + * @bug 8368527 + * @summary Stress MemoryMXBean.getTotalGcCpuTime during shutdown + * @library /test/lib + * @run main/othervm -XX:+UseZGC StressGetTotalGcCpuTimeDuringShutdown */ -import jdk.test.lib.process.OutputAnalyzer; -import static jdk.test.lib.process.ProcessTools.createTestJavaProcessBuilder; -import static jdk.test.lib.process.ProcessTools.executeProcess; +/* + * @test id=Shenandoah + * @requires vm.gc.Shenandoah + * @bug 8368527 + * @summary Stress MemoryMXBean.getTotalGcCpuTime during shutdown + * @library /test/lib + * @run main/othervm -XX:+UseShenandoahGC StressGetTotalGcCpuTimeDuringShutdown + */ import java.lang.management.ManagementFactory; import java.lang.management.MemoryMXBean; import java.lang.management.ThreadMXBean; -public class GetTotalGcCpuTime { +public class StressGetTotalGcCpuTimeDuringShutdown { static final ThreadMXBean mxThreadBean = ManagementFactory.getThreadMXBean(); static final MemoryMXBean mxMemoryBean = ManagementFactory.getMemoryMXBean(); public static void main(String[] args) throws Exception { - if (args.length > 0) { - ProcessBuilder pb = createTestJavaProcessBuilder("GetTotalGcCpuTime"); - OutputAnalyzer output = executeProcess(pb); - output.shouldNotContain("GC CPU time should"); - output.shouldHaveExitValue(0); - return; - } - try { if (!mxThreadBean.isThreadCpuTimeEnabled()) { return; } } catch (UnsupportedOperationException e) { if (mxMemoryBean.getTotalGcCpuTime() != -1) { - throw new Error("GC CPU time should be -1"); + throw new RuntimeException("GC CPU time should be -1"); } return; } @@ -71,13 +83,12 @@ public static void main(String[] args) throws Exception { while (true) { long gcCpuTimeFromThread = mxMemoryBean.getTotalGcCpuTime(); if (gcCpuTimeFromThread < -1) { - throw new Error("GC CPU time should never be less than -1 but was " + gcCpuTimeFromThread); + throw new RuntimeException("GC CPU time should never be less than -1 but was " + gcCpuTimeFromThread); } } }); + t.setDaemon(true); t.start(); } - - System.exit(0); } } From 57577ae8c4bb6c4832b7ab0ecca71445913f4368 Mon Sep 17 00:00:00 2001 From: Jonas Norlinder Date: Tue, 28 Oct 2025 13:22:41 +0100 Subject: [PATCH 12/14] Add basic test for MemoryMXBean.getTotalGcCpuTime --- .../MemoryMXBean/TestGetTotalGcCpuTime.java | 112 ++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 test/jdk/java/lang/management/MemoryMXBean/TestGetTotalGcCpuTime.java diff --git a/test/jdk/java/lang/management/MemoryMXBean/TestGetTotalGcCpuTime.java b/test/jdk/java/lang/management/MemoryMXBean/TestGetTotalGcCpuTime.java new file mode 100644 index 0000000000000..d8a760027a79b --- /dev/null +++ b/test/jdk/java/lang/management/MemoryMXBean/TestGetTotalGcCpuTime.java @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2025, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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. + */ + +/* + * @test id=Epsilon + * @requires vm.gc.Epsilon + * @bug 8368527 + * @summary Stress MemoryMXBean.getTotalGcCpuTime during shutdown + * @library /test/lib + * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC TestGetTotalGcCpuTime + */ + +/* + * @test id=Serial + * @requires vm.gc.Serial + * @bug 8368527 + * @summary Stress MemoryMXBean.getTotalGcCpuTime during shutdown + * @library /test/lib + * @run main/othervm -XX:+UseSerialGC TestGetTotalGcCpuTime + */ + +/* + * @test id=Parallel + * @requires vm.gc.Parallel + * @bug 8368527 + * @summary Stress MemoryMXBean.getTotalGcCpuTime during shutdown + * @library /test/lib + * @run main/othervm -XX:+UseParallelGC TestGetTotalGcCpuTime + */ + +/* + * @test id=G1 + * @requires vm.gc.G1 + * @bug 8368527 + * @summary Stress MemoryMXBean.getTotalGcCpuTime during shutdown + * @library /test/lib + * @run main/othervm -XX:+UseG1GC TestGetTotalGcCpuTime + */ + +/* + * @test id=ZGC + * @requires vm.gc.Z + * @bug 8368527 + * @summary Stress MemoryMXBean.getTotalGcCpuTime during shutdown + * @library /test/lib + * @run main/othervm -XX:+UseZGC TestGetTotalGcCpuTime + */ + +/* + * @test id=Shenandoah + * @requires vm.gc.Shenandoah + * @bug 8368527 + * @summary Stress MemoryMXBean.getTotalGcCpuTime during shutdown + * @library /test/lib + * @run main/othervm -XX:+UseShenandoahGC TestGetTotalGcCpuTime + */ + +import java.lang.management.ManagementFactory; +import java.lang.management.MemoryMXBean; +import java.lang.management.ThreadMXBean; + +public class TestGetTotalGcCpuTime { + static final ThreadMXBean mxThreadBean = ManagementFactory.getThreadMXBean(); + static final MemoryMXBean mxMemoryBean = ManagementFactory.getMemoryMXBean(); + static final boolean usingEpsilonGC = ManagementFactory.getRuntimeMXBean().getInputArguments().stream().anyMatch(p -> p.contains("-XX:+UseEpsilonGC")); + + public static void main(String[] args) throws Exception { + try { + if (!mxThreadBean.isThreadCpuTimeEnabled()) { + return; + } + } catch (UnsupportedOperationException e) { + if (mxMemoryBean.getTotalGcCpuTime() != -1) { + throw new RuntimeException("GC CPU time should be -1"); + } + return; + } + + System.gc(); + long gcCpuTimeFromThread = mxMemoryBean.getTotalGcCpuTime(); + + if (usingEpsilonGC) { + if (gcCpuTimeFromThread != 0) { + throw new RuntimeException("Epsilon GC can't have any GC CPU time by definition"); + } + } else { + if (gcCpuTimeFromThread <= 0) { + throw new RuntimeException("Some GC CPU time must have been reported"); + } + } + } +} From f395e8d201715b2eb35f8f8525f4ef99044ad3a0 Mon Sep 17 00:00:00 2001 From: Jonas Norlinder Date: Tue, 28 Oct 2025 13:50:28 +0100 Subject: [PATCH 13/14] Also stress-test Serial and Epsilon --- .../StressGetTotalGcCpuTimeDuringShutdown.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/test/jdk/java/lang/management/MemoryMXBean/StressGetTotalGcCpuTimeDuringShutdown.java b/test/jdk/java/lang/management/MemoryMXBean/StressGetTotalGcCpuTimeDuringShutdown.java index cba74e1b554b7..21a8b18ffd7e4 100644 --- a/test/jdk/java/lang/management/MemoryMXBean/StressGetTotalGcCpuTimeDuringShutdown.java +++ b/test/jdk/java/lang/management/MemoryMXBean/StressGetTotalGcCpuTimeDuringShutdown.java @@ -21,6 +21,24 @@ * questions. */ +/* + * @test id=Epsilon + * @requires vm.gc.Epsilon + * @bug 8368527 + * @summary Stress MemoryMXBean.getTotalGcCpuTime during shutdown + * @library /test/lib + * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC StressGetTotalGcCpuTimeDuringShutdown + */ + +/* + * @test id=Serial + * @requires vm.gc.Serial + * @bug 8368527 + * @summary Stress MemoryMXBean.getTotalGcCpuTime during shutdown + * @library /test/lib + * @run main/othervm -XX:+UseSerialGC StressGetTotalGcCpuTimeDuringShutdown + */ + /* * @test id=Parallel * @requires vm.gc.Parallel From 44f5d8647667ffb234f9554e3011deabc58d47f1 Mon Sep 17 00:00:00 2001 From: Jonas Norlinder Date: Wed, 29 Oct 2025 19:02:19 +0100 Subject: [PATCH 14/14] Fix phohensee review comments --- .../share/classes/java/lang/management/MemoryMXBean.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/java.management/share/classes/java/lang/management/MemoryMXBean.java b/src/java.management/share/classes/java/lang/management/MemoryMXBean.java index edd079e2faac5..1211d8d1c4d7d 100644 --- a/src/java.management/share/classes/java/lang/management/MemoryMXBean.java +++ b/src/java.management/share/classes/java/lang/management/MemoryMXBean.java @@ -284,7 +284,7 @@ public interface MemoryMXBean extends PlatformManagedObject { * for calculating the GC's usage of CPU time as a whole. * * @implNote The specifics on what constitutes the time spent - * in GC is highly implementation dependent. In the HotSpot + * in GC are highly implementation dependent. In the HotSpot * Virtual Machine, this time includes relevant * implementation-specific details such as driver threads, * workers, VM Operations and string deduplication (if @@ -292,7 +292,7 @@ public interface MemoryMXBean extends PlatformManagedObject { * orchestrate its work. The return value can be -1 if called * when measurement is not possible, such as during shutdown. * - * @implSpec The default implementation return {@code -1}. + * @implSpec The default implementation returns {@code -1}. * * @return the total accumulated CPU time for GC in * nanoseconds, or {@code -1}.