diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/EventInstrumentation.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/EventInstrumentation.java index 7f0ed76586a..032ccb5f4b5 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/EventInstrumentation.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/EventInstrumentation.java @@ -61,8 +61,8 @@ import jdk.jfr.internal.util.ImplicitFields; * */ public final class EventInstrumentation { - public static final long MASK_THROTTLE = 1 << 62; - public static final long MASK_THROTTLE_CHECK = 1 << 63; + public static final long MASK_THROTTLE = 1L << 62; + public static final long MASK_THROTTLE_CHECK = 1L << 63; public static final long MASK_THROTTLE_BITS = MASK_THROTTLE | MASK_THROTTLE_CHECK; public static final long MASK_THROTTLE_CHECK_SUCCESS = MASK_THROTTLE_CHECK | MASK_THROTTLE; public static final long MASK_THROTTLE_CHECK_FAIL = MASK_THROTTLE_CHECK | 0; @@ -482,6 +482,11 @@ public final class EventInstrumentation { blockCodeBuilder.ifne(durationEvent); invokestatic(blockCodeBuilder, TYPE_EVENT_CONFIGURATION, METHOD_TIME_STAMP); blockCodeBuilder.lstore(1); + if (throttled) { + blockCodeBuilder.aload(0); + blockCodeBuilder.lload(1); + putfield(blockCodeBuilder, eventClassDesc, ImplicitFields.FIELD_START_TIME); + } Label commit = blockCodeBuilder.newLabel(); blockCodeBuilder.goto_(commit); // if (duration == 0) { @@ -491,7 +496,7 @@ public final class EventInstrumentation { blockCodeBuilder.labelBinding(durationEvent); blockCodeBuilder.aload(0); getfield(blockCodeBuilder, eventClassDesc, ImplicitFields.FIELD_DURATION); - blockCodeBuilder.lconst_0(); + blockCodeBuilder.lconst_0(); // also blocks throttled event blockCodeBuilder.lcmp(); blockCodeBuilder.ifne(commit); blockCodeBuilder.aload(0); @@ -527,9 +532,7 @@ public final class EventInstrumentation { // write duration blockCodeBuilder.dup(); // stack: [EW] [EW] - blockCodeBuilder.aload(0); - // stack: [EW] [EW] [this] - getfield(blockCodeBuilder, eventClassDesc, ImplicitFields.FIELD_DURATION); + getDuration(blockCodeBuilder); // stack: [EW] [EW] [long] invokevirtual(blockCodeBuilder, TYPE_EVENT_WRITER, EventWriterMethod.PUT_LONG.method()); fieldIndex++; diff --git a/test/jdk/jdk/jfr/api/metadata/annotations/TestThrottle.java b/test/jdk/jdk/jfr/api/metadata/annotations/TestThrottle.java index da3bd311abb..89aab24b802 100644 --- a/test/jdk/jdk/jfr/api/metadata/annotations/TestThrottle.java +++ b/test/jdk/jdk/jfr/api/metadata/annotations/TestThrottle.java @@ -23,38 +23,25 @@ package jdk.jfr.api.metadata.annotations; -import java.lang.annotation.Annotation; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; +import java.io.IOException; import java.lang.reflect.Constructor; +import java.nio.file.Files; +import java.nio.file.Path; import java.time.Duration; -import java.util.HashSet; -import java.util.List; -import java.util.Map; +import java.time.Instant; import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicLong; -import java.util.concurrent.atomic.AtomicReference; -import jdk.jfr.AnnotationElement; -import jdk.jfr.Event; -import jdk.jfr.EventType; -import jdk.jfr.MetadataDefinition; -import jdk.jfr.Name; -import jdk.jfr.Threshold; import jdk.jfr.Enabled; +import jdk.jfr.Event; import jdk.jfr.Recording; -import jdk.jfr.SettingDefinition; -import jdk.jfr.SettingDescriptor; -import jdk.jfr.Throttle; -import jdk.jfr.ValueDescriptor; -import jdk.jfr.consumer.RecordedEvent; -import jdk.jfr.consumer.RecordingStream; -import jdk.test.lib.Asserts; -import jdk.test.lib.jfr.Events; import jdk.jfr.SettingControl; +import jdk.jfr.SettingDefinition; +import jdk.jfr.Threshold; +import jdk.jfr.Throttle; +import jdk.jfr.consumer.RecordedEvent; +import jdk.jfr.consumer.RecordingFile; +import jdk.jfr.consumer.RecordingStream; /** * @test @@ -65,6 +52,9 @@ import jdk.jfr.SettingControl; */ public class TestThrottle { + public static class UnthrottledEvent extends Event { + } + @Throttle("off") @Enabled(false) public static class ThrottledDisabledEvent extends Event { @@ -130,7 +120,11 @@ public class TestThrottle { public int index; } + private static Instant startTime; + public static void main(String[] args) throws Exception { + startTime = determineMinimumTime(); + testUnthrottled(); // To ensure problem is specific to throttled events testThrottleDisabled(); testThrottledOff(); testThottleZeroRate(); @@ -140,6 +134,20 @@ public class TestThrottle { testThrottleUserdefined(); } + private static void testUnthrottled() throws Exception { + testEvent(UnthrottledEvent.class, true); + } + + private static Instant determineMinimumTime() throws IOException { + try (Recording r = new Recording()) { + r.enable("jdk.JVMInformation"); + r.start(); + Path p = Path.of("start.jfr"); + r.dump(p); + return RecordingFile.readAllEvents(p).get(0).getStartTime(); + } + } + private static void testThrottleDisabled() throws Exception { testEvent(ThrottledDisabledEvent.class, false); } @@ -220,8 +228,6 @@ public class TestThrottle { if (e5.shouldCommit()) { e5.commit(); } - - r.stop(); assertEvents(r, eventName, emit ? 5 : 0); } } @@ -272,14 +278,31 @@ public class TestThrottle { private static void assertEvents(Recording r, String name, int expected) throws Exception { int count = 0; - for (RecordedEvent event : Events.fromRecording(r)) { + r.stop(); + Duration d = Duration.between(r.getStartTime(), r.getStopTime()); + Path file = Path.of("dump.jfr"); + r.dump(file); + for (RecordedEvent event : RecordingFile.readAllEvents(file)) { if (event.getEventType().getName().equals(name)) { count++; } + if (event.getDuration().isNegative()) { + System.out.println(event); + throw new Exception("Unexpected negative duration"); + } + if (event.getStartTime().isBefore(startTime)) { + System.out.println(event); + throw new Exception("Unexpected early start time"); + } + if (event.getDuration().toMillis() > 2 * d.toMillis()) { + System.out.println(event); + throw new Exception("Duration exceed twice the length of the recording"); + } } if (count != expected) { throw new Exception("Expected " + expected + " " + name + " events, but found " + count); } + Files.delete(file); } private static void assertShouldCommit(Event e, boolean expected) throws Exception {