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