1 /*
   2  * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /*
  25  * @test
  26  * @bug     6396794
  27  * @summary Check that LastGcInfo contents are reasonable
  28  * @author  Eamonn McManus
  29  *
  30  * @modules jdk.management
  31  *
  32  * @run     main/othervm -XX:-ExplicitGCInvokesConcurrent GcInfoCompositeType
  33  */
  34 // Passing "-XX:-ExplicitGCInvokesConcurrent" to force System.gc()
  35 // run on foreground when CMS is used and prevent situations when "GcInfo"
  36 // is missing even though System.gc() was successfuly processed.
  37 
  38 import java.util.*;
  39 import java.lang.management.*;
  40 import java.lang.reflect.*;
  41 import javax.management.*;
  42 import javax.management.openmbean.*;
  43 import com.sun.management.GcInfo;
  44 
  45 public class GcInfoCompositeType {
  46     private static int tested = 0;
  47 
  48     public static void main(String[] args) throws Exception {
  49         MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
  50         final ObjectName gcMXBeanPattern =
  51                 new ObjectName("java.lang:type=GarbageCollector,*");
  52         Set<ObjectName> names =
  53                 mbs.queryNames(gcMXBeanPattern, null);
  54         if (names.isEmpty())
  55             throw new Exception("Test incorrect: no GC MXBeans");
  56         System.gc();
  57         for (ObjectName n : names)
  58             tested += test(mbs, n);
  59         if (tested == 0)
  60             throw new Exception("No MXBeans were tested");
  61         System.out.println("Test passed");
  62     }
  63 
  64     private static int test(MBeanServer mbs, ObjectName n) throws Exception {
  65         System.out.println("Testing " + n);
  66         MBeanInfo mbi = mbs.getMBeanInfo(n);
  67         MBeanAttributeInfo lastGcAI = null;
  68         for (MBeanAttributeInfo mbai : mbi.getAttributes()) {
  69             if (mbai.getName().equals("LastGcInfo")) {
  70                 lastGcAI = mbai;
  71                 break;
  72             }
  73         }
  74         if (lastGcAI == null)
  75             throw new Exception("No LastGcInfo attribute");
  76         CompositeType declaredType =
  77                 (CompositeType) lastGcAI.getDescriptor().getFieldValue("openType");
  78         checkType(declaredType);
  79         CompositeData cd =
  80                 (CompositeData) mbs.getAttribute(n, "LastGcInfo");
  81         if (cd == null) {
  82             System.out.println("Value of attribute null");
  83             return 0;
  84         } else
  85             return checkType(cd.getCompositeType());
  86     }
  87 
  88     private static int checkType(CompositeType ct) throws Exception {
  89         Method[] methods = GcInfo.class.getMethods();
  90         Set<String> getters = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
  91         for (Method m : methods) {
  92             if (m.getName().startsWith("get") && m.getParameterTypes().length == 0)
  93                 getters.add(m.getName().substring(3));
  94         }
  95         Set<String> items = new HashSet<String>(ct.keySet());
  96         System.out.println("Items at start: " + items);
  97 
  98         // Now check that all the getters have a corresponding item in the
  99         // CompositeType, except the following:
 100         // getClass() inherited from Object should not be an item;
 101         // getCompositeType() inherited from CompositeData is not useful so
 102         // our hack removes it too.
 103         // Also track which items had corresponding getters, to make sure
 104         // there is at least one item which does not (GcThreadCount or
 105         // another gc-type-specific item).
 106         final String[] surplus = {"Class", "CompositeType"};
 107         for (String key : ct.keySet()) {
 108             if (getters.remove(key))
 109                 items.remove(key);
 110         }
 111         if (!getters.equals(new HashSet<String>(Arrays.asList(surplus)))) {
 112             throw new Exception("Wrong getters: " + getters);
 113         }
 114         if (items.isEmpty()) {
 115             System.out.println("No type-specific items");
 116             return 0;
 117         } else {
 118             System.out.println("Type-specific items: " + items);
 119             return 1;
 120         }
 121     }
 122 }