23
23
24
24
package gc .metaspace ;
25
25
26
- import java .lang .management . GarbageCollectorMXBean ;
26
+ import java .lang .invoke . VarHandle ;
27
27
import java .util .List ;
28
28
import java .util .ArrayList ;
29
29
183
183
* @run main/othervm -XX:+UsePerfData -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC gc.metaspace.TestMetaspacePerfCounters
184
184
*/
185
185
186
+ class PerfCounterSnapshot {
187
+ private static long getMinCapacity (String ns ) throws Exception {
188
+ return PerfCounters .findByName (ns + ".minCapacity" ).longValue ();
189
+ }
190
+
191
+ private static long getCapacity (String ns ) throws Exception {
192
+ return PerfCounters .findByName (ns + ".capacity" ).longValue ();
193
+ }
194
+
195
+ private static long getMaxCapacity (String ns ) throws Exception {
196
+ return PerfCounters .findByName (ns + ".maxCapacity" ).longValue ();
197
+ }
198
+
199
+ private static long getUsed (String ns ) throws Exception {
200
+ return PerfCounters .findByName (ns + ".used" ).longValue ();
201
+ }
202
+
203
+ public long minCapacity ;
204
+ public long maxCapacity ;
205
+ public long capacity ;
206
+ public long used ;
207
+
208
+ public void get (String ns ) throws Exception {
209
+ minCapacity = getMinCapacity (ns );
210
+ maxCapacity = getMaxCapacity (ns );
211
+ used = getUsed (ns );
212
+ capacity = getCapacity (ns );
213
+ }
214
+
215
+ public boolean consistentWith (PerfCounterSnapshot other ) {
216
+ return (minCapacity == other .minCapacity ) && (maxCapacity == other .maxCapacity ) &&
217
+ (used == other .used ) && (capacity == other .capacity );
218
+ }
219
+ }
220
+
186
221
public class TestMetaspacePerfCounters {
187
222
public static Class <?> fooClass = null ;
188
223
private static final String [] counterNames = {"minCapacity" , "maxCapacity" , "capacity" , "used" };
189
- private static final List <GarbageCollectorMXBean > gcBeans = ManagementFactoryHelper .getGarbageCollectorMXBeans ();
190
224
191
225
public static void main (String [] args ) throws Exception {
192
226
String metaspace = "sun.gc.metaspace" ;
@@ -204,32 +238,28 @@ public static void main(String[] args) throws Exception {
204
238
}
205
239
206
240
private static void checkPerfCounters (String ns ) throws Exception {
207
- long gcCountBefore ;
208
- long gcCountAfter ;
209
- long minCapacity ;
210
- long maxCapacity ;
211
- long capacity ;
212
- long used ;
213
-
214
- // The perf counter values are updated during GC and to be able to
215
- // do the assertions below we need to ensure that the values are from
216
- // the same GC cycle.
217
- do {
218
- gcCountBefore = currentGCCount ();
219
-
220
- minCapacity = getMinCapacity (ns );
221
- maxCapacity = getMaxCapacity (ns );
222
- capacity = getCapacity (ns );
223
- used = getUsed (ns );
224
-
225
- gcCountAfter = currentGCCount ();
226
- assertGTE (gcCountAfter , gcCountBefore );
227
- } while (gcCountAfter > gcCountBefore );
228
-
229
- assertGTE (minCapacity , 0L );
230
- assertGTE (used , minCapacity );
231
- assertGTE (capacity , used );
232
- assertGTE (maxCapacity , capacity );
241
+ PerfCounterSnapshot snap1 = new PerfCounterSnapshot ();
242
+ PerfCounterSnapshot snap2 = new PerfCounterSnapshot ();
243
+
244
+ final int MaxAttempts = 10 ;
245
+
246
+ for (int attempts = 0 ; ; attempts ++) {
247
+ snap1 .get (ns );
248
+ VarHandle .fullFence ();
249
+ snap2 .get (ns );
250
+
251
+ if (snap1 .consistentWith (snap2 )) {
252
+ // Got a consistent snapshot for examination.
253
+ break ;
254
+ } else if (attempts == MaxAttempts ) {
255
+ throw new Exception ("Failed to get stable reading of metaspace performance counters after " + attempts + " tries" );
256
+ }
257
+ }
258
+
259
+ assertGTE (snap1 .minCapacity , 0L );
260
+ assertGTE (snap1 .used , snap1 .minCapacity );
261
+ assertGTE (snap1 .capacity , snap1 .used );
262
+ assertGTE (snap1 .maxCapacity , snap1 .capacity );
233
263
}
234
264
235
265
private static void checkEmptyPerfCounters (String ns ) throws Exception {
@@ -243,12 +273,14 @@ private static void checkUsedIncreasesWhenLoadingClass(String ns) throws Excepti
243
273
// Need to ensure that used is up to date and that all unreachable
244
274
// classes are unloaded before doing this check.
245
275
System .gc ();
246
- long before = getUsed (ns );
276
+ PerfCounterSnapshot before = new PerfCounterSnapshot ();
277
+ before .get (ns );
247
278
fooClass = compileAndLoad ("Foo" , "public class Foo { }" );
248
279
System .gc ();
249
- long after = getUsed (ns );
280
+ PerfCounterSnapshot after = new PerfCounterSnapshot ();
281
+ after .get (ns );
250
282
251
- assertGT (after , before );
283
+ assertGT (after . used , before . used );
252
284
}
253
285
254
286
private static List <PerfCounter > countersInNamespace (String ns ) throws Exception {
@@ -267,28 +299,4 @@ private static Class<?> compileAndLoad(String name, String source) throws Except
267
299
private static boolean isUsingCompressedClassPointers () {
268
300
return Platform .is64bit () && InputArguments .contains ("-XX:+UseCompressedClassPointers" );
269
301
}
270
-
271
- private static long getMinCapacity (String ns ) throws Exception {
272
- return PerfCounters .findByName (ns + ".minCapacity" ).longValue ();
273
- }
274
-
275
- private static long getCapacity (String ns ) throws Exception {
276
- return PerfCounters .findByName (ns + ".capacity" ).longValue ();
277
- }
278
-
279
- private static long getMaxCapacity (String ns ) throws Exception {
280
- return PerfCounters .findByName (ns + ".maxCapacity" ).longValue ();
281
- }
282
-
283
- private static long getUsed (String ns ) throws Exception {
284
- return PerfCounters .findByName (ns + ".used" ).longValue ();
285
- }
286
-
287
- private static long currentGCCount () {
288
- long gcCount = 0 ;
289
- for (GarbageCollectorMXBean bean : gcBeans ) {
290
- gcCount += bean .getCollectionCount ();
291
- }
292
- return gcCount ;
293
- }
294
302
}
0 commit comments