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