Skip to content
This repository was archived by the owner on Sep 19, 2023. It is now read-only.

Commit 40df5df

Browse files
committed
8279398: jdk/jfr/api/recording/time/TestTimeMultiple.java failed with "RuntimeException: getStopTime() > afterStop"
Reviewed-by: mgronlun
1 parent ad34f03 commit 40df5df

File tree

3 files changed

+38
-30
lines changed

3 files changed

+38
-30
lines changed

src/jdk.jfr/share/classes/jdk/jfr/internal/MetadataRepository.java

Lines changed: 7 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -280,9 +280,12 @@ synchronized Instant setOutput(String filename) {
280280
if (staleMetadata) {
281281
storeDescriptorInJVM();
282282
}
283-
awaitUniqueTimestamp();
284283
jvm.setOutput(filename);
285-
long nanos = jvm.getChunkStartNanos();
284+
// Each chunk needs a unique start timestamp and
285+
// if the clock resolution is low, two chunks may
286+
// get the same timestamp. Utils.getChunkStartNanos()
287+
// ensures the timestamp is unique for the next chunk
288+
long chunkStart = Utils.getChunkStartNanos();
286289
if (filename != null) {
287290
RepositoryFiles.notifyNewFile();
288291
}
@@ -293,29 +296,7 @@ synchronized Instant setOutput(String filename) {
293296
}
294297
unregistered = false;
295298
}
296-
return Utils.epochNanosToInstant(nanos);
297-
}
298-
299-
// Each chunk needs a unique start timestamp and
300-
// if the clock resolution is low, two chunks may
301-
// get the same timestamp.
302-
private void awaitUniqueTimestamp() {
303-
if (outputChange == null) {
304-
outputChange = Instant.now();
305-
return;
306-
}
307-
while (true) {
308-
Instant time = Instant.now();
309-
if (!time.equals(outputChange)) {
310-
outputChange = time;
311-
return;
312-
}
313-
try {
314-
Thread.sleep(0, 100);
315-
} catch (InterruptedException iex) {
316-
// ignore
317-
}
318-
}
299+
return Utils.epochNanosToInstant(chunkStart);
319300
}
320301

321302
private void unregisterUnloaded() {

src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecorder.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ synchronized long start(PlatformRecording recording) {
248248
}
249249
currentChunk = newChunk;
250250
jvm.beginRecording();
251-
startNanos = jvm.getChunkStartNanos();
251+
startNanos = Utils.getChunkStartNanos();
252252
startTime = Utils.epochNanosToInstant(startNanos);
253253
if (currentChunk != null) {
254254
currentChunk.setStartTime(startTime);
@@ -269,7 +269,7 @@ synchronized long start(PlatformRecording recording) {
269269
startTime = MetadataRepository.getInstance().setOutput(p);
270270
newChunk.setStartTime(startTime);
271271
}
272-
startNanos = jvm.getChunkStartNanos();
272+
startNanos = Utils.getChunkStartNanos();
273273
startTime = Utils.epochNanosToInstant(startNanos);
274274
recording.setStartTime(startTime);
275275
recording.setState(RecordingState.RUNNING);
@@ -316,7 +316,7 @@ synchronized void stop(PlatformRecording recording) {
316316
}
317317
}
318318
OldObjectSample.emit(recording);
319-
recording.setFinalStartnanos(jvm.getChunkStartNanos());
319+
recording.setFinalStartnanos(Utils.getChunkStartNanos());
320320

321321
if (endPhysical) {
322322
RequestEngine.doChunkEnd();

src/jdk.jfr/share/classes/jdk/jfr/internal/Utils.java

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -97,6 +97,7 @@ public final class Utils {
9797
* The possible data race is benign and is worth of not introducing any contention here.
9898
*/
9999
private static Metrics[] metrics;
100+
private static Instant lastTimestamp;
100101

101102
public static void checkAccessFlightRecorder() throws SecurityException {
102103
@SuppressWarnings("removal")
@@ -866,4 +867,30 @@ public static void ensureJavaIdentifier(String name) {
866867
throw new IllegalArgumentException("'" + name + "' is not a valid Java identifier");
867868
}
868869
}
870+
871+
public static long getChunkStartNanos() {
872+
long nanos = JVM.getJVM().getChunkStartNanos();
873+
// JVM::getChunkStartNanos() may return a bumped timestamp, +1 ns or +2 ns.
874+
// Spin here to give Instant.now() a chance to catch up.
875+
awaitUniqueTimestamp();
876+
return nanos;
877+
}
878+
879+
private static void awaitUniqueTimestamp() {
880+
if (lastTimestamp == null) {
881+
lastTimestamp = Instant.now(); // lazy initialization
882+
}
883+
while (true) {
884+
Instant time = Instant.now();
885+
if (!time.equals(lastTimestamp)) {
886+
lastTimestamp = time;
887+
return;
888+
}
889+
try {
890+
Thread.sleep(0, 100);
891+
} catch (InterruptedException iex) {
892+
// ignore
893+
}
894+
}
895+
}
869896
}

0 commit comments

Comments
 (0)