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