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  * @modules jdk.management
  30  * @run     main/othervm -XX:-ExplicitGCInvokesConcurrent GcInfoCompositeType
  31  */
  32 // Passing "-XX:-ExplicitGCInvokesConcurrent" to force System.gc()
  33 // run on foreground when CMS is used and prevent situations when "GcInfo"
  34 // is missing even though System.gc() was successfuly processed.
  35 
  36 import java.util.*;
  37 import java.lang.management.*;
  38 import java.lang.reflect.*;
  39 import javax.management.*;
  40 import javax.management.openmbean.*;
  41 import com.sun.management.GcInfo;
  42 
  43 public class GcInfoCompositeType {
  44     private static int tested = 0;
  45 
  46     public static void main(String[] args) throws Exception {
  47         MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
  48         final ObjectName gcMXBeanPattern =
  49                 new ObjectName("java.lang:type=GarbageCollector,*");
  50         Set<ObjectName> names =
  51                 mbs.queryNames(gcMXBeanPattern, null);
  52         if (names.isEmpty())
  53             throw new Exception("Test incorrect: no GC MXBeans");
  54         System.gc();
  55         for (ObjectName n : names)
  56             tested += test(mbs, n);
  57         if (tested == 0)
  58             throw new Exception("No MXBeans were tested");
  59         System.out.println("Test passed");
  60     }
  61 
  62     private static int test(MBeanServer mbs, ObjectName n) throws Exception {
  63         System.out.println("Testing " + n);
  64         MBeanInfo mbi = mbs.getMBeanInfo(n);
  65         MBeanAttributeInfo lastGcAI = null;
  66         for (MBeanAttributeInfo mbai : mbi.getAttributes()) {
  67             if (mbai.getName().equals("LastGcInfo")) {
  68                 lastGcAI = mbai;
  69                 break;
  70             }
  71         }
  72         if (lastGcAI == null)
  73             throw new Exception("No LastGcInfo attribute");
  74         CompositeType declaredType =
  75                 (CompositeType) lastGcAI.getDescriptor().getFieldValue("openType");
  76         checkType(declaredType);
  77         CompositeData cd =
  78                 (CompositeData) mbs.getAttribute(n, "LastGcInfo");
  79         if (cd == null) {
  80             System.out.println("Value of attribute null");
  81             return 0;
  82         } else
  83             return checkType(cd.getCompositeType());
  84     }
  85 
  86     private static int checkType(CompositeType ct) throws Exception {
  87         Method[] methods = GcInfo.class.getMethods();
  88         Set<String> getters = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
  89         for (Method m : methods) {
  90             if (m.getName().startsWith("get") && m.getParameterTypes().length == 0)
  91                 getters.add(m.getName().substring(3));
  92         }
  93         Set<String> items = new HashSet<String>(ct.keySet());
  94         System.out.println("Items at start: " + items);
  95 
  96         // Now check that all the getters have a corresponding item in the
  97         // CompositeType, except the following:
  98         // getClass() inherited from Object should not be an item;
  99         // getCompositeType() inherited from CompositeData is not useful so
 100         // our hack removes it too.
 101         // Also track which items had corresponding getters, to make sure
 102         // there is at least one item which does not (GcThreadCount or
 103         // another gc-type-specific item).
 104         final String[] surplus = {"Class", "CompositeType"};
 105         for (String key : ct.keySet()) {
 106             if (getters.remove(key))
 107                 items.remove(key);
 108         }
 109         if (!getters.equals(new HashSet<String>(Arrays.asList(surplus)))) {
 110             throw new Exception("Wrong getters: " + getters);
 111         }
 112         if (items.isEmpty()) {
 113             System.out.println("No type-specific items");
 114             return 0;
 115         } else {
 116             System.out.println("Type-specific items: " + items);
 117             return 1;
 118         }
 119     }
 120 }