From 4d6668e7ee492de828bc36afea7daa535532a2b1 Mon Sep 17 00:00:00 2001 From: Erik Gahlin Date: Tue, 4 Oct 2022 11:45:53 +0000 Subject: [PATCH] 8294242: JFR: jfr print doesn't handle infinite duration well Reviewed-by: mgronlun --- src/jdk.jfr/share/classes/jdk/jfr/Timespan.java | 4 +++- .../classes/jdk/jfr/consumer/RecordedObject.java | 8 ++++++++ .../classes/jdk/jfr/internal/tool/PrettyWriter.java | 5 +++++ .../jdk/jdk/jfr/api/consumer/TestRecordedObject.java | 12 +++++++++++- 4 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/jdk.jfr/share/classes/jdk/jfr/Timespan.java b/src/jdk.jfr/share/classes/jdk/jfr/Timespan.java index 7989306b375..3cde59333a4 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/Timespan.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/Timespan.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,6 +32,8 @@ import java.lang.annotation.Target; /** * Event field annotation, specifies that the value is a duration. + *

+ * If the annotated value equals {@code Long.MAX_VALUE), it represents forever. * * @since 9 */ diff --git a/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedObject.java b/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedObject.java index 73036cf6ce4..8a42ee68cfc 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedObject.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedObject.java @@ -31,6 +31,7 @@ import java.io.StringWriter; import java.time.Duration; import java.time.Instant; import java.time.OffsetDateTime; +import java.time.temporal.ChronoUnit; import java.util.Comparator; import java.util.List; import java.util.Objects; @@ -755,6 +756,10 @@ public sealed class RecordedObject * the following types: {@code long}, {@code int}, {@code short}, {@code char}, * and {@code byte}. *

+ * If the committed event value was {@code Long.MAX_VALUE}, + * regardless of the unit set by {@code @Timespan}, this method returns + * {@link ChronoUnit.FOREVER.getDuration()}. + *

* It's possible to index into a nested object using {@code "."} (for example, * {@code "aaa.bbb"}). *

@@ -811,6 +816,9 @@ public sealed class RecordedObject if (timespan == Long.MIN_VALUE) { return Duration.ofSeconds(Long.MIN_VALUE, 0); } + if (timespan == Long.MAX_VALUE) { + return ChronoUnit.FOREVER.getDuration(); + } Timespan ts = v.getAnnotation(Timespan.class); if (ts != null) { switch (ts.value()) { diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/PrettyWriter.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/PrettyWriter.java index d355763c7ed..8378433ef5d 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/PrettyWriter.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/PrettyWriter.java @@ -29,6 +29,7 @@ import java.io.PrintWriter; import java.time.Duration; import java.time.OffsetDateTime; import java.time.format.DateTimeFormatter; +import java.time.temporal.ChronoUnit; import java.util.ArrayList; import java.util.List; import java.util.StringJoiner; @@ -553,6 +554,10 @@ public final class PrettyWriter extends EventPrintWriter { println("N/A"); return true; } + if (d.equals(ChronoUnit.FOREVER.getDuration())) { + println("Forever"); + return true; + } println(Utils.formatDuration(d)); return true; } diff --git a/test/jdk/jdk/jfr/api/consumer/TestRecordedObject.java b/test/jdk/jdk/jfr/api/consumer/TestRecordedObject.java index ee9c547de14..af7b5dfbf90 100644 --- a/test/jdk/jdk/jfr/api/consumer/TestRecordedObject.java +++ b/test/jdk/jdk/jfr/api/consumer/TestRecordedObject.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ package jdk.jfr.api.consumer; import java.io.IOException; import java.time.Duration; import java.time.Instant; +import java.time.temporal.ChronoUnit; import java.util.Arrays; import java.util.HashSet; import java.util.List; @@ -92,6 +93,12 @@ public class TestRecordedObject { @Timespan(Timespan.SECONDS) long durationSeconds = DURATION_VALUE.toSeconds(); + @Timespan(Timespan.SECONDS) + long foreverMillis = Long.MAX_VALUE; + + @Timespan(Timespan.NANOSECONDS) + long foreverNanoseconds = Long.MAX_VALUE; + @Timestamp(Timestamp.MILLISECONDS_SINCE_EPOCH) long instantMillis = 1000; @@ -179,6 +186,9 @@ public class TestRecordedObject { Asserts.assertEquals(event.getDuration("durationMicros"), DURATION_VALUE); Asserts.assertEquals(event.getDuration("durationMillis"), DURATION_VALUE); Asserts.assertEquals(event.getDuration("durationSeconds"), DURATION_VALUE); + Asserts.assertEquals(event.getDuration("foreverMillis"), ChronoUnit.FOREVER.getDuration()); + Asserts.assertEquals(event.getDuration("foreverNanoseconds"), ChronoUnit.FOREVER.getDuration()); + Asserts.assertEquals(event.getInstant("instantMillis").toEpochMilli(), 1000L); if (!event.getInstant("instantTicks").isBefore(INSTANT_VALUE)) { throw new AssertionError("Expected start time of JVM to before call to Instant.now()");