8279398: jdk/jfr/api/recording/time/TestTimeMultiple.java failed with "RuntimeException: getStopTime() > afterStop"

Reviewed-by: mgronlun
This commit is contained in:
Erik Gahlin 2022-01-10 15:07:49 +00:00
parent ad34f03b54
commit 40df5df95e
3 changed files with 38 additions and 30 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, 2021, 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
@ -280,9 +280,12 @@ public final class MetadataRepository {
if (staleMetadata) {
storeDescriptorInJVM();
}
awaitUniqueTimestamp();
jvm.setOutput(filename);
long nanos = jvm.getChunkStartNanos();
// Each chunk needs a unique start timestamp and
// if the clock resolution is low, two chunks may
// get the same timestamp. Utils.getChunkStartNanos()
// ensures the timestamp is unique for the next chunk
long chunkStart = Utils.getChunkStartNanos();
if (filename != null) {
RepositoryFiles.notifyNewFile();
}
@ -293,29 +296,7 @@ public final class MetadataRepository {
}
unregistered = false;
}
return Utils.epochNanosToInstant(nanos);
}
// Each chunk needs a unique start timestamp and
// if the clock resolution is low, two chunks may
// get the same timestamp.
private void awaitUniqueTimestamp() {
if (outputChange == null) {
outputChange = Instant.now();
return;
}
while (true) {
Instant time = Instant.now();
if (!time.equals(outputChange)) {
outputChange = time;
return;
}
try {
Thread.sleep(0, 100);
} catch (InterruptedException iex) {
// ignore
}
}
return Utils.epochNanosToInstant(chunkStart);
}
private void unregisterUnloaded() {

View File

@ -248,7 +248,7 @@ public final class PlatformRecorder {
}
currentChunk = newChunk;
jvm.beginRecording();
startNanos = jvm.getChunkStartNanos();
startNanos = Utils.getChunkStartNanos();
startTime = Utils.epochNanosToInstant(startNanos);
if (currentChunk != null) {
currentChunk.setStartTime(startTime);
@ -269,7 +269,7 @@ public final class PlatformRecorder {
startTime = MetadataRepository.getInstance().setOutput(p);
newChunk.setStartTime(startTime);
}
startNanos = jvm.getChunkStartNanos();
startNanos = Utils.getChunkStartNanos();
startTime = Utils.epochNanosToInstant(startNanos);
recording.setStartTime(startTime);
recording.setState(RecordingState.RUNNING);
@ -316,7 +316,7 @@ public final class PlatformRecorder {
}
}
OldObjectSample.emit(recording);
recording.setFinalStartnanos(jvm.getChunkStartNanos());
recording.setFinalStartnanos(Utils.getChunkStartNanos());
if (endPhysical) {
RequestEngine.doChunkEnd();

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, 2021, 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
@ -97,6 +97,7 @@ public final class Utils {
* The possible data race is benign and is worth of not introducing any contention here.
*/
private static Metrics[] metrics;
private static Instant lastTimestamp;
public static void checkAccessFlightRecorder() throws SecurityException {
@SuppressWarnings("removal")
@ -866,4 +867,30 @@ public final class Utils {
throw new IllegalArgumentException("'" + name + "' is not a valid Java identifier");
}
}
public static long getChunkStartNanos() {
long nanos = JVM.getJVM().getChunkStartNanos();
// JVM::getChunkStartNanos() may return a bumped timestamp, +1 ns or +2 ns.
// Spin here to give Instant.now() a chance to catch up.
awaitUniqueTimestamp();
return nanos;
}
private static void awaitUniqueTimestamp() {
if (lastTimestamp == null) {
lastTimestamp = Instant.now(); // lazy initialization
}
while (true) {
Instant time = Instant.now();
if (!time.equals(lastTimestamp)) {
lastTimestamp = time;
return;
}
try {
Thread.sleep(0, 100);
} catch (InterruptedException iex) {
// ignore
}
}
}
}