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