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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -280,9 +280,12 @@ public final class MetadataRepository {
if (staleMetadata) { if (staleMetadata) {
storeDescriptorInJVM(); storeDescriptorInJVM();
} }
awaitUniqueTimestamp();
jvm.setOutput(filename); 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) { if (filename != null) {
RepositoryFiles.notifyNewFile(); RepositoryFiles.notifyNewFile();
} }
@ -293,29 +296,7 @@ public final class MetadataRepository {
} }
unregistered = false; unregistered = false;
} }
return Utils.epochNanosToInstant(nanos); return Utils.epochNanosToInstant(chunkStart);
}
// 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
}
}
} }
private void unregisterUnloaded() { private void unregisterUnloaded() {

View File

@ -248,7 +248,7 @@ public final class PlatformRecorder {
} }
currentChunk = newChunk; currentChunk = newChunk;
jvm.beginRecording(); jvm.beginRecording();
startNanos = jvm.getChunkStartNanos(); startNanos = Utils.getChunkStartNanos();
startTime = Utils.epochNanosToInstant(startNanos); startTime = Utils.epochNanosToInstant(startNanos);
if (currentChunk != null) { if (currentChunk != null) {
currentChunk.setStartTime(startTime); currentChunk.setStartTime(startTime);
@ -269,7 +269,7 @@ public final class PlatformRecorder {
startTime = MetadataRepository.getInstance().setOutput(p); startTime = MetadataRepository.getInstance().setOutput(p);
newChunk.setStartTime(startTime); newChunk.setStartTime(startTime);
} }
startNanos = jvm.getChunkStartNanos(); startNanos = Utils.getChunkStartNanos();
startTime = Utils.epochNanosToInstant(startNanos); startTime = Utils.epochNanosToInstant(startNanos);
recording.setStartTime(startTime); recording.setStartTime(startTime);
recording.setState(RecordingState.RUNNING); recording.setState(RecordingState.RUNNING);
@ -316,7 +316,7 @@ public final class PlatformRecorder {
} }
} }
OldObjectSample.emit(recording); OldObjectSample.emit(recording);
recording.setFinalStartnanos(jvm.getChunkStartNanos()); recording.setFinalStartnanos(Utils.getChunkStartNanos());
if (endPhysical) { if (endPhysical) {
RequestEngine.doChunkEnd(); 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * 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. * The possible data race is benign and is worth of not introducing any contention here.
*/ */
private static Metrics[] metrics; private static Metrics[] metrics;
private static Instant lastTimestamp;
public static void checkAccessFlightRecorder() throws SecurityException { public static void checkAccessFlightRecorder() throws SecurityException {
@SuppressWarnings("removal") @SuppressWarnings("removal")
@ -866,4 +867,30 @@ public final class Utils {
throw new IllegalArgumentException("'" + name + "' is not a valid Java identifier"); 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
}
}
}
} }