MXBeanBehavior.java revision 11884:b45c81ca8671
1/* 2 * Copyright (c) 2005, 2015, 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 6320211 27 * @summary Check that java.lang.management MXBeans have the same behavior 28 * as user MXBeans 29 * @author Eamonn McManus 30 * @modules java.management 31 * jdk.management 32 * @run main/othervm MXBeanBehavior 33 */ 34 35import java.lang.management.*; 36import java.lang.reflect.*; 37import java.util.*; 38import javax.management.*; 39 40public class MXBeanBehavior { 41 // Exclude list: list of platform MBeans that are not MXBeans 42 public static final HashSet<String> excludeList = new HashSet<>( 43 Arrays.asList("com.sun.management:type=DiagnosticCommand")); 44 45 public static void main(String[] args) throws Exception { 46 MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); 47 48 /* Test that all the MBeans in the java.* and com.sun.management* 49 domains are MXBeans with the appropriate behavior. */ 50 Set<ObjectName> names = mbs.queryNames(new ObjectName("java.*:*"), 51 null); 52 names.addAll(mbs.queryNames(new ObjectName("com.sun.management*:*"), 53 null)); 54 for (ObjectName name : names) 55 test(mbs, name); 56 57 /* Now do some rudimentary testing of inter-MXBean references. 58 It should be possible for a user MXBean to return e.g. the 59 CompilationMXBean from the platform from an attribute of 60 type CompilationMXBean, and have the MXBean infrastructure 61 map this into that MXBean's standard ObjectName. It should 62 also be possible for a proxy for this user MXBean to have 63 this attribute's value mapped back into a CompilationMXBean 64 instance, which however will be another proxy rather than 65 the original object. Finally, it should be possible to set 66 the attribute in the user's MXBean through a proxy, giving 67 the real CompilationMXBean as an argument, and have this be 68 translated into that MXBean's standard ObjectName. The 69 user's MXBean will receive a proxy in this case, though we 70 don't check that. */ 71 ObjectName refName = new ObjectName("d:type=CompilationRef"); 72 mbs.registerMBean(new CompilationImpl(), refName); 73 CompilationRefMXBean refProxy = 74 JMX.newMXBeanProxy(mbs, refName, CompilationRefMXBean.class); 75 refProxy.getCompilationMXBean(); 76 refProxy.setCompilationMXBean(ManagementFactory.getCompilationMXBean()); 77 ObjectName on = 78 (ObjectName) mbs.getAttribute(refName, "CompilationMXBean"); 79 checkEqual(on, new ObjectName(ManagementFactory.COMPILATION_MXBEAN_NAME), 80 "Referenced object name"); 81 mbs.setAttribute(refName, new Attribute("CompilationMXBean", on)); 82 83 System.out.println("TEST PASSED"); 84 } 85 86 /* Check the behavior of this MXBean to ensure that it conforms to 87 what is expected of all MXBeans as detailed in 88 javax.management.MXBean. Its MBeanInfo should have a 89 Descriptor with the fields mxbean and interfaceClassName, and 90 furthermore we know that our implementation sets immutableInfo 91 here. Each attribute should have Descriptor with the fields 92 openType and originalType that have appropriate values. We 93 don't currently check operations though the same considerations 94 would apply there. (If the MBeanInfo and MBeanAttributeInfo 95 tests pass we can reasonably suppose that this MXBean will 96 behave the same as all other MXBeans, so MBeanOperationInfo, 97 MBeanNotificationInfo, and MBeanConstructorInfo will be covered 98 by generic MXBean tests. 99 */ 100 private static void test(MBeanServer mbs, ObjectName name) throws Exception { 101 if(excludeList.contains(name.getCanonicalName())) { 102 // Skipping not MXBean objects. 103 return; 104 } 105 System.out.println("Testing: " + name); 106 107 MBeanInfo mbi = mbs.getMBeanInfo(name); 108 Descriptor mbid = mbi.getDescriptor(); 109 Object[] values = mbid.getFieldValues("immutableInfo", 110 "interfaceClassName", 111 "mxbean"); 112 checkEqual(values[0], "true", name + " immutableInfo field"); 113 checkEqual(values[2], "true", name + " mxbean field"); 114 String interfaceClassName = (String) values[1]; 115 if (!mbs.isInstanceOf(name, interfaceClassName)) { 116 throw new RuntimeException(name + " not instance of " + 117 interfaceClassName); 118 } 119 Class interfaceClass = Class.forName(interfaceClassName); 120 for (MBeanAttributeInfo mbai : mbi.getAttributes()) { 121 Descriptor mbaid = mbai.getDescriptor(); 122 Object[] avalues = mbaid.getFieldValues("openType", 123 "originalType"); 124 if (avalues[0] == null || avalues[1] == null) { 125 throw new RuntimeException("Null attribute descriptor fields: " + 126 Arrays.toString(avalues)); 127 } 128 if (mbai.isReadable()) { 129 String mname = (mbai.isIs() ? "is" : "get") + mbai.getName(); 130 Method m = interfaceClass.getMethod(mname); 131 Type t = m.getGenericReturnType(); 132 String ret = 133 (t instanceof Class) ? ((Class) t).getName() : t.toString(); 134 if (!ret.equals(avalues[1])) { 135 final String msg = 136 name + " attribute " + mbai.getName() + " has wrong " + 137 "originalType: " + avalues[1] + " vs " + ret; 138 throw new RuntimeException(msg); 139 } 140 } 141 } 142 } 143 144 private static void checkEqual(Object x, Object y, String what) { 145 final boolean eq; 146 if (x == y) 147 eq = true; 148 else if (x == null) 149 eq = false; 150 else 151 eq = x.equals(y); 152 if (!eq) 153 throw new RuntimeException(what + " should be " + y + ", is " + x); 154 } 155 156 public static interface CompilationRefMXBean { 157 public CompilationMXBean getCompilationMXBean(); 158 public void setCompilationMXBean(CompilationMXBean mxb); 159 } 160 161 public static class CompilationImpl implements CompilationRefMXBean { 162 public CompilationMXBean getCompilationMXBean() { 163 return ManagementFactory.getCompilationMXBean(); 164 } 165 166 public void setCompilationMXBean(CompilationMXBean mxb) { 167 if (mxb == ManagementFactory.getCompilationMXBean()) 168 return; 169 MBeanServerInvocationHandler mbsih = (MBeanServerInvocationHandler) 170 Proxy.getInvocationHandler(mxb); 171 ObjectName expectedName; 172 try { 173 expectedName = 174 new ObjectName(ManagementFactory.COMPILATION_MXBEAN_NAME); 175 } catch (MalformedObjectNameException e) { 176 throw new RuntimeException(e); 177 } 178 checkEqual(mbsih.getObjectName(), expectedName, 179 "Proxy name in setCompilationMXBean"); 180 } 181 } 182} 183