1 # HG changeset patch 2 # User brutisso 3 # Date 1426775154 -3600 4 # Thu Mar 19 15:25:54 2015 +0100 5 # Node ID b8448a4717da948b02f073dd274a94b50f095838 6 # Parent b31893aea8834508c334f4cef3b1d3bf410b4ac7 7 8027962: Per-phase timing measurements for strong roots processing 8 Reviewed-by: tschatzl, ecaspole 9 10 diff --git a/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp b/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp 11 --- a/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp 12 +++ b/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp 13 @@ -249,7 +249,24 @@ 14 15 _gc_par_phases[GCWorkerStart] = new WorkerDataArray<double>(max_gc_threads, "GC Worker Start (ms)", false, G1Log::LevelFiner, 2); 16 _gc_par_phases[ExtRootScan] = new WorkerDataArray<double>(max_gc_threads, "Ext Root Scanning (ms)", true, G1Log::LevelFiner, 2); 17 - _gc_par_phases[SATBFiltering] = new WorkerDataArray<double>(max_gc_threads, "SATB Filtering (ms)", true, G1Log::LevelFiner, 2); 18 + 19 + // Root scanning phases 20 + _gc_par_phases[ThreadRoots] = new WorkerDataArray<double>(max_gc_threads, "Thread Roots (ms)", true, G1Log::LevelFinest, 3); 21 + _gc_par_phases[StringTableRoots] = new WorkerDataArray<double>(max_gc_threads, "StringTable Roots (ms)", true, G1Log::LevelFinest, 3); 22 + _gc_par_phases[UniverseRoots] = new WorkerDataArray<double>(max_gc_threads, "Universe Roots (ms)", true, G1Log::LevelFinest, 3); 23 + _gc_par_phases[JNIRoots] = new WorkerDataArray<double>(max_gc_threads, "JNI Handles Roots (ms)", true, G1Log::LevelFinest, 3); 24 + _gc_par_phases[ObjectSynchronizerRoots] = new WorkerDataArray<double>(max_gc_threads, "ObjectSynchronizer Roots (ms)", true, G1Log::LevelFinest, 3); 25 + _gc_par_phases[FlatProfilerRoots] = new WorkerDataArray<double>(max_gc_threads, "FlatProfiler Roots (ms)", true, G1Log::LevelFinest, 3); 26 + _gc_par_phases[ManagementRoots] = new WorkerDataArray<double>(max_gc_threads, "Management Roots (ms)", true, G1Log::LevelFinest, 3); 27 + _gc_par_phases[SystemDictionaryRoots] = new WorkerDataArray<double>(max_gc_threads, "SystemDictionary Roots (ms)", true, G1Log::LevelFinest, 3); 28 + _gc_par_phases[CLDGRoots] = new WorkerDataArray<double>(max_gc_threads, "CLDG Roots (ms)", true, G1Log::LevelFinest, 3); 29 + _gc_par_phases[JVMTIRoots] = new WorkerDataArray<double>(max_gc_threads, "JVMTI Roots (ms)", true, G1Log::LevelFinest, 3); 30 + _gc_par_phases[CodeCacheRoots] = new WorkerDataArray<double>(max_gc_threads, "CodeCache Roots (ms)", true, G1Log::LevelFinest, 3); 31 + _gc_par_phases[CMRefRoots] = new WorkerDataArray<double>(max_gc_threads, "CM RefProcessor Roots (ms)", true, G1Log::LevelFinest, 3); 32 + _gc_par_phases[WaitForStrongCLD] = new WorkerDataArray<double>(max_gc_threads, "Wait For Strong CLD (ms)", true, G1Log::LevelFinest, 3); 33 + _gc_par_phases[WeakCLDRoots] = new WorkerDataArray<double>(max_gc_threads, "Weak CLD Roots (ms)", true, G1Log::LevelFinest, 3); 34 + _gc_par_phases[SATBFiltering] = new WorkerDataArray<double>(max_gc_threads, "SATB Filtering (ms)", true, G1Log::LevelFinest, 3); 35 + 36 _gc_par_phases[UpdateRS] = new WorkerDataArray<double>(max_gc_threads, "Update RS (ms)", true, G1Log::LevelFiner, 2); 37 _gc_par_phases[ScanRS] = new WorkerDataArray<double>(max_gc_threads, "Scan RS (ms)", true, G1Log::LevelFiner, 2); 38 _gc_par_phases[CodeRoots] = new WorkerDataArray<double>(max_gc_threads, "Code Root Scanning (ms)", true, G1Log::LevelFiner, 2); 39 @@ -282,8 +299,6 @@ 40 _gc_par_phases[i]->reset(); 41 } 42 43 - _gc_par_phases[SATBFiltering]->set_enabled(mark_in_progress); 44 - 45 _gc_par_phases[StringDedupQueueFixup]->set_enabled(G1StringDedup::is_enabled()); 46 _gc_par_phases[StringDedupTableFixup]->set_enabled(G1StringDedup::is_enabled()); 47 } 48 diff --git a/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp b/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp 49 --- a/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp 50 +++ b/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp 51 @@ -41,6 +41,20 @@ 52 enum GCParPhases { 53 GCWorkerStart, 54 ExtRootScan, 55 + ThreadRoots, 56 + StringTableRoots, 57 + UniverseRoots, 58 + JNIRoots, 59 + ObjectSynchronizerRoots, 60 + FlatProfilerRoots, 61 + ManagementRoots, 62 + SystemDictionaryRoots, 63 + CLDGRoots, 64 + JVMTIRoots, 65 + CodeCacheRoots, 66 + CMRefRoots, 67 + WaitForStrongCLD, 68 + WeakCLDRoots, 69 SATBFiltering, 70 UpdateRS, 71 ScanRS, 72 diff --git a/src/share/vm/gc_implementation/g1/g1RootProcessor.cpp b/src/share/vm/gc_implementation/g1/g1RootProcessor.cpp 73 --- a/src/share/vm/gc_implementation/g1/g1RootProcessor.cpp 74 +++ b/src/share/vm/gc_implementation/g1/g1RootProcessor.cpp 75 @@ -128,6 +128,7 @@ 76 uint worker_i) { 77 // First scan the shared roots. 78 double ext_roots_start = os::elapsedTime(); 79 + G1GCPhaseTimes* phase_times = _g1h->g1_policy()->phase_times(); 80 81 BufferingOopClosure buf_scan_non_heap_roots(scan_non_heap_roots); 82 BufferingOopClosure buf_scan_non_heap_weak_roots(scan_non_heap_weak_roots); 83 @@ -142,7 +143,9 @@ 84 trace_metadata ? scan_strong_clds : NULL, 85 scan_strong_clds, 86 trace_metadata ? NULL : scan_weak_clds, 87 - &root_code_blobs); 88 + &root_code_blobs, 89 + phase_times, 90 + worker_i); 91 92 // This is the point where this worker thread will not find more strong CLDs/nmethods. 93 // Report this so G1 can synchronize the strong and weak CLDs/nmethods processing. 94 @@ -150,24 +153,34 @@ 95 worker_has_discovered_all_strong_classes(); 96 } 97 98 - process_vm_roots(strong_roots, weak_roots); 99 + process_vm_roots(strong_roots, weak_roots, phase_times, worker_i); 100 101 - // Now the CM ref_processor roots. 102 - if (!_process_strong_tasks->is_task_claimed(G1RP_PS_refProcessor_oops_do)) { 103 - // We need to treat the discovered reference lists of the 104 - // concurrent mark ref processor as roots and keep entries 105 - // (which are added by the marking threads) on them live 106 - // until they can be processed at the end of marking. 107 - _g1h->ref_processor_cm()->weak_oops_do(&buf_scan_non_heap_roots); 108 + { 109 + // Now the CM ref_processor roots. 110 + G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::CMRefRoots, worker_i); 111 + if (!_process_strong_tasks->is_task_claimed(G1RP_PS_refProcessor_oops_do)) { 112 + // We need to treat the discovered reference lists of the 113 + // concurrent mark ref processor as roots and keep entries 114 + // (which are added by the marking threads) on them live 115 + // until they can be processed at the end of marking. 116 + _g1h->ref_processor_cm()->weak_oops_do(&buf_scan_non_heap_roots); 117 + } 118 } 119 120 if (trace_metadata) { 121 - // Barrier to make sure all workers passed 122 - // the strong CLD and strong nmethods phases. 123 - wait_until_all_strong_classes_discovered(); 124 + { 125 + G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::WaitForStrongCLD, worker_i); 126 + // Barrier to make sure all workers passed 127 + // the strong CLD and strong nmethods phases. 128 + wait_until_all_strong_classes_discovered(); 129 + } 130 131 // Now take the complement of the strong CLDs. 132 + G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::WeakCLDRoots, worker_i); 133 ClassLoaderDataGraph::roots_cld_do(NULL, scan_weak_clds); 134 + } else { 135 + phase_times->record_time_secs(G1GCPhaseTimes::WaitForStrongCLD, worker_i, 0.0); 136 + phase_times->record_time_secs(G1GCPhaseTimes::WeakCLDRoots, worker_i, 0.0); 137 } 138 139 // Finish up any enqueued closure apps (attributed as object copy time). 140 @@ -177,7 +190,6 @@ 141 double obj_copy_time_sec = buf_scan_non_heap_roots.closure_app_seconds() 142 + buf_scan_non_heap_weak_roots.closure_app_seconds(); 143 144 - G1GCPhaseTimes* phase_times = _g1h->g1_policy()->phase_times(); 145 phase_times->record_time_secs(G1GCPhaseTimes::ObjCopy, worker_i, obj_copy_time_sec); 146 147 double ext_root_time_sec = os::elapsedTime() - ext_roots_start - obj_copy_time_sec; 148 @@ -201,8 +213,8 @@ 149 CLDClosure* clds, 150 CodeBlobClosure* blobs) { 151 152 - process_java_roots(oops, clds, clds, NULL, blobs); 153 - process_vm_roots(oops, NULL); 154 + process_java_roots(oops, clds, clds, NULL, blobs, NULL, 0); 155 + process_vm_roots(oops, NULL, NULL, 0); 156 157 _process_strong_tasks->all_tasks_completed(); 158 } 159 @@ -211,8 +223,8 @@ 160 CLDClosure* clds, 161 CodeBlobClosure* blobs) { 162 163 - process_java_roots(oops, NULL, clds, clds, NULL); 164 - process_vm_roots(oops, oops); 165 + process_java_roots(oops, NULL, clds, clds, NULL, NULL, 0); 166 + process_vm_roots(oops, oops, NULL, 0); 167 168 if (!_process_strong_tasks->is_task_claimed(G1RP_PS_CodeCache_oops_do)) { 169 CodeCache::blobs_do(blobs); 170 @@ -225,60 +237,95 @@ 171 CLDClosure* thread_stack_clds, 172 CLDClosure* strong_clds, 173 CLDClosure* weak_clds, 174 - CodeBlobClosure* strong_code) { 175 + CodeBlobClosure* strong_code, 176 + G1GCPhaseTimes* phase_times, 177 + uint worker_i) { 178 assert(thread_stack_clds == NULL || weak_clds == NULL, "There is overlap between those, only one may be set"); 179 // Iterating over the CLDG and the Threads are done early to allow us to 180 // first process the strong CLDs and nmethods and then, after a barrier, 181 // let the thread process the weak CLDs and nmethods. 182 - 183 - if (!_process_strong_tasks->is_task_claimed(G1RP_PS_ClassLoaderDataGraph_oops_do)) { 184 - ClassLoaderDataGraph::roots_cld_do(strong_clds, weak_clds); 185 + { 186 + G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::CLDGRoots, worker_i); 187 + if (!_process_strong_tasks->is_task_claimed(G1RP_PS_ClassLoaderDataGraph_oops_do)) { 188 + ClassLoaderDataGraph::roots_cld_do(strong_clds, weak_clds); 189 + } 190 } 191 192 - Threads::possibly_parallel_oops_do(strong_roots, thread_stack_clds, strong_code); 193 + { 194 + G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::ThreadRoots, worker_i); 195 + Threads::possibly_parallel_oops_do(strong_roots, thread_stack_clds, strong_code); 196 + } 197 } 198 199 void G1RootProcessor::process_vm_roots(OopClosure* strong_roots, 200 - OopClosure* weak_roots) { 201 - 202 - if (!_process_strong_tasks->is_task_claimed(G1RP_PS_Universe_oops_do)) { 203 - Universe::oops_do(strong_roots); 204 + OopClosure* weak_roots, 205 + G1GCPhaseTimes* phase_times, 206 + uint worker_i) { 207 + { 208 + G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::UniverseRoots, worker_i); 209 + if (!_process_strong_tasks->is_task_claimed(G1RP_PS_Universe_oops_do)) { 210 + Universe::oops_do(strong_roots); 211 + } 212 } 213 214 - if (!_process_strong_tasks->is_task_claimed(G1RP_PS_JNIHandles_oops_do)) { 215 - JNIHandles::oops_do(strong_roots); 216 + { 217 + G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::JNIRoots, worker_i); 218 + if (!_process_strong_tasks->is_task_claimed(G1RP_PS_JNIHandles_oops_do)) { 219 + JNIHandles::oops_do(strong_roots); 220 + } 221 } 222 223 - if (!_process_strong_tasks-> is_task_claimed(G1RP_PS_ObjectSynchronizer_oops_do)) { 224 - ObjectSynchronizer::oops_do(strong_roots); 225 + { 226 + G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::ObjectSynchronizerRoots, worker_i); 227 + if (!_process_strong_tasks-> is_task_claimed(G1RP_PS_ObjectSynchronizer_oops_do)) { 228 + ObjectSynchronizer::oops_do(strong_roots); 229 + } 230 } 231 232 - if (!_process_strong_tasks->is_task_claimed(G1RP_PS_FlatProfiler_oops_do)) { 233 - FlatProfiler::oops_do(strong_roots); 234 + { 235 + G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::FlatProfilerRoots, worker_i); 236 + if (!_process_strong_tasks->is_task_claimed(G1RP_PS_FlatProfiler_oops_do)) { 237 + FlatProfiler::oops_do(strong_roots); 238 + } 239 } 240 241 - if (!_process_strong_tasks->is_task_claimed(G1RP_PS_Management_oops_do)) { 242 - Management::oops_do(strong_roots); 243 + { 244 + G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::ManagementRoots, worker_i); 245 + if (!_process_strong_tasks->is_task_claimed(G1RP_PS_Management_oops_do)) { 246 + Management::oops_do(strong_roots); 247 + } 248 } 249 250 - if (!_process_strong_tasks->is_task_claimed(G1RP_PS_jvmti_oops_do)) { 251 - JvmtiExport::oops_do(strong_roots); 252 + { 253 + G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::JVMTIRoots, worker_i); 254 + if (!_process_strong_tasks->is_task_claimed(G1RP_PS_jvmti_oops_do)) { 255 + JvmtiExport::oops_do(strong_roots); 256 + } 257 } 258 259 - if (!_process_strong_tasks->is_task_claimed(G1RP_PS_SystemDictionary_oops_do)) { 260 - SystemDictionary::roots_oops_do(strong_roots, weak_roots); 261 + { 262 + G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::SystemDictionaryRoots, worker_i); 263 + if (!_process_strong_tasks->is_task_claimed(G1RP_PS_SystemDictionary_oops_do)) { 264 + SystemDictionary::roots_oops_do(strong_roots, weak_roots); 265 + } 266 } 267 268 - // All threads execute the following. A specific chunk of buckets 269 - // from the StringTable are the individual tasks. 270 - if (weak_roots != NULL) { 271 - StringTable::possibly_parallel_oops_do(weak_roots); 272 + { 273 + G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::StringTableRoots, worker_i); 274 + // All threads execute the following. A specific chunk of buckets 275 + // from the StringTable are the individual tasks. 276 + if (weak_roots != NULL) { 277 + StringTable::possibly_parallel_oops_do(weak_roots); 278 + } 279 } 280 } 281 282 void G1RootProcessor::scan_remembered_sets(G1ParPushHeapRSClosure* scan_rs, 283 OopClosure* scan_non_heap_weak_roots, 284 uint worker_i) { 285 + G1GCPhaseTimes* phase_times = _g1h->g1_policy()->phase_times(); 286 + G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::CodeCacheRoots, worker_i); 287 + 288 // Now scan the complement of the collection set. 289 G1CodeBlobClosure scavenge_cs_nmethods(scan_non_heap_weak_roots); 290 291 diff --git a/src/share/vm/gc_implementation/g1/g1RootProcessor.hpp b/src/share/vm/gc_implementation/g1/g1RootProcessor.hpp 292 --- a/src/share/vm/gc_implementation/g1/g1RootProcessor.hpp 293 +++ b/src/share/vm/gc_implementation/g1/g1RootProcessor.hpp 294 @@ -32,6 +32,7 @@ 295 class CLDClosure; 296 class CodeBlobClosure; 297 class G1CollectedHeap; 298 +class G1GCPhaseTimes; 299 class G1ParPushHeapRSClosure; 300 class Monitor; 301 class OopClosure; 302 @@ -74,10 +75,14 @@ 303 CLDClosure* thread_stack_clds, 304 CLDClosure* scan_strong_clds, 305 CLDClosure* scan_weak_clds, 306 - CodeBlobClosure* scan_strong_code); 307 + CodeBlobClosure* scan_strong_code, 308 + G1GCPhaseTimes* phase_times, 309 + uint worker_i); 310 311 void process_vm_roots(OopClosure* scan_non_heap_roots, 312 - OopClosure* scan_non_heap_weak_roots); 313 + OopClosure* scan_non_heap_weak_roots, 314 + G1GCPhaseTimes* phase_times, 315 + uint worker_i); 316 317 public: 318 G1RootProcessor(G1CollectedHeap* g1h); 319 diff --git a/test/gc/g1/TestGCLogMessages.java b/test/gc/g1/TestGCLogMessages.java 320 --- a/test/gc/g1/TestGCLogMessages.java 321 +++ b/test/gc/g1/TestGCLogMessages.java 322 @@ -1,5 +1,5 @@ 323 /* 324 - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. 325 + * Copyright (c) 2014, 2015 Oracle and/or its affiliates. All rights reserved. 326 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 327 * 328 * This code is free software; you can redistribute it and/or modify it 329 @@ -23,7 +23,7 @@ 330 331 /* 332 * @test TestGCLogMessages 333 - * @bug 8035406 8027295 8035398 8019342 8027959 334 + * @bug 8035406 8027295 8035398 8019342 8027959 8027962 335 * @summary Ensure that the PrintGCDetails output for a minor GC with G1 336 * includes the expected necessary messages. 337 * @key gc 338 @@ -34,128 +34,158 @@ 339 import com.oracle.java.testlibrary.OutputAnalyzer; 340 341 public class TestGCLogMessages { 342 - public static void main(String[] args) throws Exception { 343 - testNormalLogs(); 344 - testWithToSpaceExhaustionLogs(); 345 - } 346 347 - private static void testNormalLogs() throws Exception { 348 + private enum Level { 349 + OFF, FINER, FINEST; 350 + public boolean lessOrEqualTo(Level other) { 351 + return this.compareTo(other) < 0; 352 + } 353 + } 354 355 - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC", 356 - "-Xmx10M", 357 - GCTest.class.getName()); 358 + private class LogMessageWithLevel { 359 + String message; 360 + Level level; 361 362 - OutputAnalyzer output = new OutputAnalyzer(pb.start()); 363 + public LogMessageWithLevel(String message, Level level) { 364 + this.message = message; 365 + this.level = level; 366 + } 367 + }; 368 369 - output.shouldNotContain("[Redirty Cards"); 370 - output.shouldNotContain("[Parallel Redirty"); 371 - output.shouldNotContain("[Redirtied Cards"); 372 - output.shouldNotContain("[Code Root Purge"); 373 - output.shouldNotContain("[String Dedup Fixup"); 374 - output.shouldNotContain("[Young Free CSet"); 375 - output.shouldNotContain("[Non-Young Free CSet"); 376 - output.shouldNotContain("[Humongous Reclaim"); 377 - output.shouldHaveExitValue(0); 378 + private LogMessageWithLevel allLogMessages[] = new LogMessageWithLevel[] { 379 + // Ext Root Scan 380 + new LogMessageWithLevel("Thread Roots (ms)", Level.FINEST), 381 + new LogMessageWithLevel("StringTable Roots (ms)", Level.FINEST), 382 + new LogMessageWithLevel("Universe Roots (ms)", Level.FINEST), 383 + new LogMessageWithLevel("JNI Handles Roots (ms)", Level.FINEST), 384 + new LogMessageWithLevel("ObjectSynchronizer Roots (ms)", Level.FINEST), 385 + new LogMessageWithLevel("FlatProfiler Roots", Level.FINEST), 386 + new LogMessageWithLevel("Management Roots", Level.FINEST), 387 + new LogMessageWithLevel("SystemDictionary Roots", Level.FINEST), 388 + new LogMessageWithLevel("CLDG Roots", Level.FINEST), 389 + new LogMessageWithLevel("JVMTI Roots", Level.FINEST), 390 + new LogMessageWithLevel("CodeCache Roots", Level.FINEST), 391 + new LogMessageWithLevel("SATB Filtering", Level.FINEST), 392 + new LogMessageWithLevel("CM RefProcessor Roots", Level.FINEST), 393 + new LogMessageWithLevel("Wait For Strong CLD", Level.FINEST), 394 + new LogMessageWithLevel("Weak CLD Roots", Level.FINEST), 395 + // Redirty Cards 396 + new LogMessageWithLevel("Redirty Cards", Level.FINER), 397 + new LogMessageWithLevel("Parallel Redirty", Level.FINEST), 398 + new LogMessageWithLevel("Redirtied Cards", Level.FINEST), 399 + // Misc Top-level 400 + new LogMessageWithLevel("Code Root Purge", Level.FINER), 401 + new LogMessageWithLevel("String Dedup Fixup", Level.FINER), 402 + // Free CSet 403 + new LogMessageWithLevel("Young Free CSet", Level.FINEST), 404 + new LogMessageWithLevel("Non-Young Free CSet", Level.FINEST), 405 + // Humongous Eager Reclaim 406 + new LogMessageWithLevel("Humongous Reclaim", Level.FINER), 407 + }; 408 409 - pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC", 410 - "-XX:+UseStringDeduplication", 411 - "-Xmx10M", 412 - "-XX:+PrintGCDetails", 413 - GCTest.class.getName()); 414 + void checkMessagesAtLevel(OutputAnalyzer output, LogMessageWithLevel messages[], Level level) throws Exception { 415 + for (LogMessageWithLevel l : messages) { 416 + if (level.lessOrEqualTo(l.level)) { 417 + output.shouldNotContain(l.message); 418 + } else { 419 + output.shouldContain(l.message); 420 + } 421 + } 422 + } 423 424 - output = new OutputAnalyzer(pb.start()); 425 + public static void main(String[] args) throws Exception { 426 + new TestGCLogMessages().testNormalLogs(); 427 + new TestGCLogMessages().testWithToSpaceExhaustionLogs(); 428 + } 429 430 - output.shouldContain("[Redirty Cards"); 431 - output.shouldNotContain("[Parallel Redirty"); 432 - output.shouldNotContain("[Redirtied Cards"); 433 - output.shouldContain("[Code Root Purge"); 434 - output.shouldContain("[String Dedup Fixup"); 435 - output.shouldNotContain("[Young Free CSet"); 436 - output.shouldNotContain("[Non-Young Free CSet"); 437 - output.shouldContain("[Humongous Reclaim"); 438 - output.shouldNotContain("[Humongous Total"); 439 - output.shouldNotContain("[Humongous Candidate"); 440 - output.shouldNotContain("[Humongous Reclaimed"); 441 - output.shouldHaveExitValue(0); 442 + private void testNormalLogs() throws Exception { 443 444 - pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC", 445 - "-XX:+UseStringDeduplication", 446 - "-Xmx10M", 447 - "-XX:+PrintGCDetails", 448 - "-XX:+UnlockExperimentalVMOptions", 449 - "-XX:G1LogLevel=finest", 450 - GCTest.class.getName()); 451 + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC", 452 + "-Xmx10M", 453 + GCTest.class.getName()); 454 455 - output = new OutputAnalyzer(pb.start()); 456 + OutputAnalyzer output = new OutputAnalyzer(pb.start()); 457 + checkMessagesAtLevel(output, allLogMessages, Level.OFF); 458 + output.shouldHaveExitValue(0); 459 460 - output.shouldContain("[Redirty Cards"); 461 - output.shouldContain("[Parallel Redirty"); 462 - output.shouldContain("[Redirtied Cards"); 463 - output.shouldContain("[Code Root Purge"); 464 - output.shouldContain("[String Dedup Fixup"); 465 - output.shouldContain("[Young Free CSet"); 466 - output.shouldContain("[Non-Young Free CSet"); 467 - output.shouldContain("[Humongous Reclaim"); 468 - output.shouldContain("[Humongous Total"); 469 - output.shouldContain("[Humongous Candidate"); 470 - output.shouldContain("[Humongous Reclaimed"); 471 - output.shouldHaveExitValue(0); 472 - } 473 + pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC", 474 + "-XX:+UseStringDeduplication", 475 + "-Xmx10M", 476 + "-XX:+PrintGCDetails", 477 + GCTest.class.getName()); 478 479 - private static void testWithToSpaceExhaustionLogs() throws Exception { 480 - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC", 481 - "-Xmx10M", 482 - "-Xmn5M", 483 - "-XX:+PrintGCDetails", 484 - GCTestWithToSpaceExhaustion.class.getName()); 485 + output = new OutputAnalyzer(pb.start()); 486 + checkMessagesAtLevel(output, allLogMessages, Level.FINER); 487 488 - OutputAnalyzer output = new OutputAnalyzer(pb.start()); 489 - output.shouldContain("[Evacuation Failure"); 490 - output.shouldNotContain("[Recalculate Used"); 491 - output.shouldNotContain("[Remove Self Forwards"); 492 - output.shouldNotContain("[Restore RemSet"); 493 - output.shouldHaveExitValue(0); 494 + pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC", 495 + "-XX:+UseStringDeduplication", 496 + "-Xmx10M", 497 + "-XX:+PrintGCDetails", 498 + "-XX:+UnlockExperimentalVMOptions", 499 + "-XX:G1LogLevel=finest", 500 + GCTest.class.getName()); 501 502 - pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC", 503 - "-Xmx10M", 504 - "-Xmn5M", 505 - "-XX:+PrintGCDetails", 506 - "-XX:+UnlockExperimentalVMOptions", 507 - "-XX:G1LogLevel=finest", 508 - GCTestWithToSpaceExhaustion.class.getName()); 509 + output = new OutputAnalyzer(pb.start()); 510 + checkMessagesAtLevel(output, allLogMessages, Level.FINEST); 511 + output.shouldHaveExitValue(0); 512 + } 513 514 - output = new OutputAnalyzer(pb.start()); 515 - output.shouldContain("[Evacuation Failure"); 516 - output.shouldContain("[Recalculate Used"); 517 - output.shouldContain("[Remove Self Forwards"); 518 - output.shouldContain("[Restore RemSet"); 519 - output.shouldHaveExitValue(0); 520 - } 521 + LogMessageWithLevel exhFailureMessages[] = new LogMessageWithLevel[] { 522 + new LogMessageWithLevel("Evacuation Failure", Level.FINER), 523 + new LogMessageWithLevel("Recalculate Used", Level.FINEST), 524 + new LogMessageWithLevel("Remove Self Forwards", Level.FINEST), 525 + new LogMessageWithLevel("Restore RemSet", Level.FINEST), 526 + }; 527 528 - static class GCTest { 529 - private static byte[] garbage; 530 - public static void main(String [] args) { 531 - System.out.println("Creating garbage"); 532 - // create 128MB of garbage. This should result in at least one GC 533 - for (int i = 0; i < 1024; i++) { 534 - garbage = new byte[128 * 1024]; 535 - } 536 - System.out.println("Done"); 537 + private void testWithToSpaceExhaustionLogs() throws Exception { 538 + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC", 539 + "-Xmx32M", 540 + "-Xmn16M", 541 + "-XX:+PrintGCDetails", 542 + GCTestWithToSpaceExhaustion.class.getName()); 543 + 544 + OutputAnalyzer output = new OutputAnalyzer(pb.start()); 545 + checkMessagesAtLevel(output, exhFailureMessages, Level.FINER); 546 + output.shouldHaveExitValue(0); 547 + 548 + pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC", 549 + "-Xmx32M", 550 + "-Xmn16M", 551 + "-XX:+PrintGCDetails", 552 + "-XX:+UnlockExperimentalVMOptions", 553 + "-XX:G1LogLevel=finest", 554 + GCTestWithToSpaceExhaustion.class.getName()); 555 + 556 + output = new OutputAnalyzer(pb.start()); 557 + checkMessagesAtLevel(output, exhFailureMessages, Level.FINEST); 558 + output.shouldHaveExitValue(0); 559 } 560 - } 561 562 - static class GCTestWithToSpaceExhaustion { 563 - private static byte[] garbage; 564 - private static byte[] largeObject; 565 - public static void main(String [] args) { 566 - largeObject = new byte[5*1024*1024]; 567 - System.out.println("Creating garbage"); 568 - // create 128MB of garbage. This should result in at least one GC, 569 - // some of them with to-space exhaustion. 570 - for (int i = 0; i < 1024; i++) { 571 - garbage = new byte[128 * 1024]; 572 - } 573 - System.out.println("Done"); 574 + static class GCTest { 575 + private static byte[] garbage; 576 + public static void main(String [] args) { 577 + System.out.println("Creating garbage"); 578 + // create 128MB of garbage. This should result in at least one GC 579 + for (int i = 0; i < 1024; i++) { 580 + garbage = new byte[128 * 1024]; 581 + } 582 + System.out.println("Done"); 583 + } 584 } 585 - } 586 + 587 + static class GCTestWithToSpaceExhaustion { 588 + private static byte[] garbage; 589 + private static byte[] largeObject; 590 + public static void main(String [] args) { 591 + largeObject = new byte[16*1024*1024]; 592 + System.out.println("Creating garbage"); 593 + // create 128MB of garbage. This should result in at least one GC, 594 + // some of them with to-space exhaustion. 595 + for (int i = 0; i < 1024; i++) { 596 + garbage = new byte[128 * 1024]; 597 + } 598 + System.out.println("Done"); 599 + } 600 + } 601 } 602 +