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