From da0d9598d049b17c04da95b61214b093c97fb60e Mon Sep 17 00:00:00 2001 From: Erik Gahlin Date: Mon, 4 Aug 2025 10:41:21 +0000 Subject: [PATCH] 8364190: JFR: RemoteRecordingStream withers don't work Reviewed-by: mgronlun --- .../management/jfr/RemoteRecordingStream.java | 14 +- .../jfr/jmx/streaming/TestEnableDisable.java | 4 +- .../jdk/jfr/jmx/streaming/TestWithers.java | 141 ++++++++++++++++++ 3 files changed, 151 insertions(+), 8 deletions(-) create mode 100644 test/jdk/jdk/jfr/jmx/streaming/TestWithers.java diff --git a/src/jdk.management.jfr/share/classes/jdk/management/jfr/RemoteRecordingStream.java b/src/jdk.management.jfr/share/classes/jdk/management/jfr/RemoteRecordingStream.java index 862781802fc..a8752e159ad 100644 --- a/src/jdk.management.jfr/share/classes/jdk/management/jfr/RemoteRecordingStream.java +++ b/src/jdk.management.jfr/share/classes/jdk/management/jfr/RemoteRecordingStream.java @@ -98,10 +98,12 @@ public final class RemoteRecordingStream implements EventStream { private final FlightRecorderMXBean mbean; private final long recordingId; + private final String identifier; - RemoteSettings(FlightRecorderMXBean mbean, long recordingId) { + RemoteSettings(FlightRecorderMXBean mbean, long recordingId, String identifier) { this.mbean = mbean; this.recordingId = recordingId; + this.identifier = identifier; } @Override @@ -111,7 +113,7 @@ public final class RemoteRecordingStream implements EventStream { // FlightRecorderMXBean implementation always returns // new instance of Map so no need to create new here. Map newSettings = getEventSettings(); - newSettings.put(name, value); + newSettings.put(identifier + "#" + name, value); mbean.setRecordingSettings(recordingId, newSettings); } @@ -340,9 +342,9 @@ public final class RemoteRecordingStream implements EventStream { */ public EventSettings disable(String name) { Objects.requireNonNull(name, "name"); - EventSettings s = ManagementSupport.newEventSettings(new RemoteSettings(mbean, recordingId)); + EventSettings s = ManagementSupport.newEventSettings(new RemoteSettings(mbean, recordingId, name)); try { - return s.with(name + "#" + ENABLED, "false"); + return s.with(ENABLED, "false"); } catch (Exception e) { ManagementSupport.logDebug(e.getMessage()); close(); @@ -364,9 +366,9 @@ public final class RemoteRecordingStream implements EventStream { */ public EventSettings enable(String name) { Objects.requireNonNull(name, "name"); - EventSettings s = ManagementSupport.newEventSettings(new RemoteSettings(mbean, recordingId)); + EventSettings s = ManagementSupport.newEventSettings(new RemoteSettings(mbean, recordingId, name)); try { - return s.with(name + "#" + ENABLED, "true"); + return s.with(ENABLED, "true"); } catch (Exception e) { ManagementSupport.logDebug(e.getMessage()); close(); diff --git a/test/jdk/jdk/jfr/jmx/streaming/TestEnableDisable.java b/test/jdk/jdk/jfr/jmx/streaming/TestEnableDisable.java index 06e9691cfa2..5b1435c9d9d 100644 --- a/test/jdk/jdk/jfr/jmx/streaming/TestEnableDisable.java +++ b/test/jdk/jdk/jfr/jmx/streaming/TestEnableDisable.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -36,7 +36,7 @@ import jdk.management.jfr.RemoteRecordingStream; /** * @test * @requires vm.flagless - * @summary Tests that event settings for a RemoteRecordingStream can be changed + * @summary Tests that the enabled setting can be configured for a RemoteRecordingStream * @requires vm.hasJFR * @library /test/lib /test/jdk * @run main/othervm jdk.jfr.jmx.streaming.TestEnableDisable diff --git a/test/jdk/jdk/jfr/jmx/streaming/TestWithers.java b/test/jdk/jdk/jfr/jmx/streaming/TestWithers.java new file mode 100644 index 00000000000..933337ef76b --- /dev/null +++ b/test/jdk/jdk/jfr/jmx/streaming/TestWithers.java @@ -0,0 +1,141 @@ +/* + * 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. + */ +package jdk.jfr.jmx.streaming; + +import java.lang.management.ManagementFactory; +import java.time.Duration; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; +import java.util.function.Consumer; +import java.util.function.Predicate; + +import javax.management.MBeanServerConnection; + +import jdk.jfr.Event; +import jdk.jfr.EventSettings; +import jdk.jfr.FlightRecorder; +import jdk.jfr.Name; +import jdk.jfr.Period; +import jdk.jfr.StackTrace; +import jdk.jfr.Threshold; +import jdk.jfr.consumer.RecordedEvent; +import jdk.jfr.consumer.RecordedStackTrace; +import jdk.management.jfr.RemoteRecordingStream; + +/** + * @test + * @requires vm.flagless + * @summary Tests that event settings for a RemoteRecordingStream can be changed + * @requires vm.hasJFR + * @library /test/lib /test/jdk + * @run main/othervm jdk.jfr.jmx.streaming.TestWithers + */ +public class TestWithers { + private static final Set RESULT = Collections.synchronizedSet(new HashSet<>()); + + @Name("AA") + @StackTrace(false) + static class A extends Event { + } + + @Name("BB") + @StackTrace(true) + static class B extends Event { + } + + @Name("CC") + @Threshold("10 h") + static class C extends Event { + } + + @Name("DD") + @Threshold("10 h") + static class D extends Event { + } + + @Name("EE") + @StackTrace(false) + static class E extends Event { + } + + @Name("FF") + @Period("10 h") + static class F extends Event { + } + + public static void main(String... args) throws Exception { + MBeanServerConnection conn = ManagementFactory.getPlatformMBeanServer(); + try (RemoteRecordingStream stream = new RemoteRecordingStream(conn)) { + addCheck(stream, es -> es.withStackTrace(), "AA", TestWithers::hasStackTrace); + addCheck(stream, es -> es.withoutStackTrace(), "BB", e -> !hasStackTrace(e)); + addCheck(stream, es -> es.withThreshold(Duration.ofMillis(0)), "CC", e -> true); + addCheck(stream, es -> es.withoutThreshold(), "DD", e -> true); + addCheck(stream, es -> es.with("stackTrace", "true"), "EE", TestWithers::hasStackTrace); + addCheck(stream, es -> es.withPeriod(Duration.ofMillis(700)), "FF", e -> true); + FlightRecorder.addPeriodicEvent(F.class, () -> { + F f = new F(); + f.commit(); + }); + stream.onFlush(() -> { + System.out.println(RESULT); + if (RESULT.size() == 6) { + stream.close(); + } + }); + + stream.startAsync(); + A a = new A(); + a.commit(); + + B b = new B(); + b.commit(); + + C c = new C(); + c.commit(); + + D d = new D(); + d.commit(); + + E e = new E(); + e.commit(); + + stream.awaitTermination(); + } + } + + private static void addCheck(RemoteRecordingStream stream, Consumer es, String eventName, Predicate validator) { + es.accept(stream.enable(eventName)); + stream.onEvent(eventName, e -> { + System.out.println(e); + if (validator.test(e)) { + RESULT.add(eventName); + } + }); + } + + private static boolean hasStackTrace(RecordedEvent e) { + RecordedStackTrace rs = e.getStackTrace(); + return rs != null && !rs.getFrames().isEmpty(); + } +} \ No newline at end of file