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