23
23
24
24
package jdk .jfr .jcmd ;
25
25
26
+ import java .time .Instant ;
26
27
import java .util .concurrent .CountDownLatch ;
27
28
28
29
import jdk .jfr .Recording ;
30
+ import jdk .jfr .consumer .RecordedEvent ;
29
31
import jdk .jfr .consumer .RecordingStream ;
30
32
import jdk .test .lib .process .OutputAnalyzer ;
31
33
/**
40
42
* -XX:+UseG1GC jdk.jfr.jcmd.TestJcmdView
41
43
*/
42
44
public class TestJcmdView {
45
+ private static volatile Instant lastTimestamp ;
43
46
44
47
public static void main (String ... args ) throws Throwable {
45
48
CountDownLatch jvmInformation = new CountDownLatch (1 );
@@ -60,22 +63,27 @@ public static void main(String... args) throws Throwable {
60
63
rs .onEvent ("jdk.JVMInformation" , e -> {
61
64
jvmInformation .countDown ();
62
65
System .out .println (e );
66
+ storeLastTimestamp (e );
63
67
});
64
68
rs .onEvent ("jdk.SystemGC" , e -> {
65
69
systemGC .countDown ();
66
70
System .out .println (e );
71
+ storeLastTimestamp (e );
67
72
});
68
73
rs .onEvent ("jdk.GCHeapSummary" , e -> {
69
74
gcHeapSummary .countDown ();
70
75
System .out .println (e );
76
+ storeLastTimestamp (e );
71
77
});
72
78
rs .onEvent ("jdk.OldGarbageCollection" , e -> {
73
79
oldCollection .countDown ();
74
80
System .out .println (e );
81
+ storeLastTimestamp (e );
75
82
});
76
83
rs .onEvent ("jdk.GarbageCollection" , e -> {
77
84
garbageCollection .countDown ();
78
85
System .out .println (e );
86
+ storeLastTimestamp (e );
79
87
});
80
88
rs .startAsync ();
81
89
// Emit some GC events
@@ -87,6 +95,16 @@ public static void main(String... args) throws Throwable {
87
95
systemGC .await ();
88
96
gcHeapSummary .await ();
89
97
oldCollection .countDown ();
98
+ // Wait for Instant.now() to advance 1 s past the last event timestamp.
99
+ // The rationale for this is twofold:
100
+ // - DcmdView starts one second before Instant.now() (to make the command
101
+ // responsive for the user).
102
+ // - Instant.now() and the event timestamp use different time sources
103
+ // and they need to synchronize.
104
+ Instant end = lastTimestamp .plusSeconds (1 );
105
+ while (Instant .now ().isBefore (end )) {
106
+ Thread .sleep (10 );
107
+ }
90
108
// Test events that are in the current chunk
91
109
testEventType ();
92
110
testFormView ();
@@ -101,6 +119,13 @@ public static void main(String... args) throws Throwable {
101
119
}
102
120
}
103
121
122
+ private static void storeLastTimestamp (RecordedEvent e ) {
123
+ Instant time = e .getEndTime ();
124
+ if (lastTimestamp == null || time .isAfter (lastTimestamp )) {
125
+ lastTimestamp = time ;
126
+ }
127
+ }
128
+
104
129
private static void rotate () {
105
130
try (Recording r = new Recording ()) {
106
131
r .start ();
0 commit comments