1 /* 2 * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 3 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. 4 */ 5 import java.util.ArrayList; 6 import java.util.List; 7 import java.util.HashMap; 8 9 import jrockit.jfr.TestRecording; 10 import oracle.jrockit.jfr.parser.FLREvent; 11 import oracle.jrockit.jfr.parser.FLRStruct; 12 13 import static jrockit.Asserts.*; 14 15 /* 16 * @test TestHeapSummaryEventConcurrentCMS 17 * @key jfr 18 * @library ../common 19 * @run main/othervm -XX:+UnlockCommercialFeatures -XX:+FlightRecorder -XX:+UseConcMarkSweepGC -XX:+ExplicitGCInvokesConcurrent -XX:+UnlockExperimentalVMOptions -XX:-UseFastUnorderedTimeStamps TestHeapSummaryEventConcurrentCMS 20 */ 21 public class TestHeapSummaryEventConcurrentCMS { 22 private static final String gcPath = "vm/gc/collector/garbage_collection"; 23 private static final String heapSummaryPath = "vm/gc/heap/summary"; 24 private static final String cmsGCName = "ConcurrentMarkSweep"; 25 26 public static void main(String[] args) throws Exception { 27 TestRecording r = new TestRecording(); 28 try { 29 enableEvent(r, heapSummaryPath); 30 enableEvent(r, gcPath); 31 32 r.start(); 33 34 // Need to two GCs in order to ensure at least one heap summary 35 // event from a concurrent CMS cycle 36 System.gc(); 37 System.gc(); 38 39 r.stop(); 40 41 List<FLREvent> allEvents = getAllEvents(r); 42 43 List<FLREvent> gcEvents = filterEventsOnPath(allEvents, gcPath); 44 assertTrue(gcEvents.size() > 0, 45 "Expected at least one " + gcPath + " event"); 46 47 List<FLREvent> heapSummaryEvents = filterEventsOnPath(allEvents, heapSummaryPath); 48 assertTrue(heapSummaryEvents.size() > 0, 49 "Expected at least one " + heapSummaryPath + " event"); 50 51 List<FLREvent> cmsEvents = filterGCEventsOnCollector(gcEvents, cmsGCName); 52 assertTrue(cmsEvents.size() > 0, 53 "Expected at least one " + gcPath + " event for collector " + cmsGCName); 54 55 List<Integer> cmsGCIds = mapGCEventsToGCIds(cmsEvents); 56 List<FLREvent> cmsHeapSummaryEvents = 57 filterHeapSummaryEventsOnGCIds(heapSummaryEvents, cmsGCIds); 58 59 HashMap<Integer, FLREvent> gcIdToHeapSummaryBefore = 60 mapGCIdToHeapSummary("Before GC", cmsHeapSummaryEvents); 61 HashMap<Integer, FLREvent> gcIdToHeapSummaryAfter = 62 mapGCIdToHeapSummary("After GC", cmsHeapSummaryEvents); 63 64 for (Integer gcId : cmsGCIds) { 65 assertTrue(gcIdToHeapSummaryBefore.get(gcId) != null, 66 "Expected a " + heapSummaryPath + " event before " + 67 gcPath + " event with id " + gcId); 68 assertTrue(gcIdToHeapSummaryAfter.get(gcId) != null, 69 "Expected a " + heapSummaryPath + " event after " + 70 gcPath + " event with id " + gcId); 71 } 72 73 int numHeapSummaryBefore = gcIdToHeapSummaryBefore.size(); 74 int numHeapSummaryAfter = gcIdToHeapSummaryAfter.size(); 75 if (numHeapSummaryBefore != numHeapSummaryAfter) { 76 // Can happen if the last System.gc() did not send a 77 // vm/gc/collector/garbage_collection event 78 79 assertTrue(numHeapSummaryBefore == numHeapSummaryAfter + 1, 80 "Expected at most one more " + heapSummaryPath); 81 82 FLREvent last = heapSummaryEvents.get(heapSummaryEvents.size() - 1); 83 assertFalse(cmsGCIds.contains(getGCId(last)), 84 "Expected the last " + heapSummaryPath + " event to not " + 85 "have a corresponding " + gcPath + " event"); 86 } 87 } catch (Throwable t) { 88 r.copyTo("TestHeapSummaryEventConcurrentCMS.jfr"); 89 throw t; 90 } finally { 91 r.close(); 92 } 93 } 94 95 private static void enableEvent(TestRecording r, String path) throws Exception { 96 r.createJVMSetting(path, true, false, 0, 0); 97 } 98 99 private static List<FLREvent> getAllEvents(TestRecording r) throws Exception { 100 return r.parser().findJVMEvents(".*"); 101 } 102 103 private static List<FLREvent> filterEventsOnPath(List<FLREvent> events, String path) throws Exception { 104 List<FLREvent> result = new ArrayList<FLREvent>(); 105 for (FLREvent e : events) { 106 if (e.getPath().equals(path)) { 107 result.add(e); 108 } 109 } 110 return result; 111 } 112 113 private static List<FLREvent> filterGCEventsOnCollector(List<FLREvent> events, String gcName) throws Exception { 114 List<FLREvent> result = new ArrayList<FLREvent>(); 115 for (FLREvent e : events) { 116 if (getGCName(e).equals(gcName)) { 117 result.add(e); 118 } 119 } 120 return result; 121 } 122 123 private static List<Integer> mapGCEventsToGCIds(List<FLREvent> events) throws Exception { 124 List<Integer> result = new ArrayList<Integer>(); 125 for (FLREvent e : events) { 126 result.add((Integer) e.getValue("gcId")); 127 } 128 return result; 129 } 130 131 private static List<FLREvent> filterHeapSummaryEventsOnGCIds(List<FLREvent> events, List<Integer> gcIds) 132 throws Exception { 133 List<FLREvent> result = new ArrayList<FLREvent>(); 134 for (FLREvent e : events) { 135 Integer gcId = (Integer) e.getValue("gcId"); 136 if (gcIds.contains(gcId)) { 137 result.add(e); 138 } 139 } 140 return result; 141 } 142 143 private static HashMap<Integer, FLREvent> mapGCIdToHeapSummary(String when, List<FLREvent> events) throws Exception { 144 HashMap<Integer, FLREvent> map = new HashMap<Integer, FLREvent>(); 145 for (FLREvent e : events) { 146 if (getWhen(e).equals(when)) { 147 map.put(getGCId(e), e); 148 } 149 } 150 151 return map; 152 } 153 154 private static String getWhen(FLREvent e) throws Exception { 155 FLRStruct s = (FLRStruct) e.getResolvedValue("when"); 156 return (String) s.getValue("when"); 157 } 158 159 private static String getGCName(FLREvent e) throws Exception { 160 FLRStruct s = (FLRStruct) e.getResolvedValue("name"); 161 String ret = (String) s.getValue("name"); 162 return ret; 163 } 164 165 private static Integer getGCId(FLREvent e) throws Exception { 166 return (Integer) e.getValue("gcId"); 167 } 168 } 169