Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/test/javax/management/remote/mandatory/loading/TargetMBeanTest.java
38867 views
/*1* Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/*24* @test25* @bug 491042826* @summary Tests target MBean class loader used before JSR 160 loader27* @author Eamonn McManus28* @run clean TargetMBeanTest29* @run build TargetMBeanTest30* @run main TargetMBeanTest31*/3233/*34The JSR 160 spec says that, when invoking a method (or setting an35attribute or creating) on a target MBean, that MBean's class loader36is used to deserialize parameters. The problem is that the RMI37connector protocol wraps these parameters as MarshalledObjects.38When you call get() on a MarshalledObject, the context class loader39is used to deserialize, so if we set this to the target MBean's40class loader everything should work. EXCEPT that MarshalledObject41first tries to load classes using the first class loader it finds in42the caller's stack. If our JSR 160 implementation is part of J2SE,43it will not find any such class loader (only the system class44loader). But if it's standalone, then it will find the class loader45of the JSR 160 implementation. If the class name of a parameter is46known to both the 160 loader and the target MBean loader, then we47will use the wrong loader for deserialization and the attempt to48invoke the target MBean with the deserialized object will fail.4950We test this as follows. We fabricate an MLet that has the same set51of URLs as the 160 class loader, which we assume is the system class52loader (or at least, it is a URLClassLoader). This MLet is53therefore a "shadow class loader" -- for every class name known to54the 160 class loader, it can load the same name, but the result is55not the same class, since it has not been loaded by the same loader.56Then, we use the MLet to create an RMIConnectorServer MBean. This57MBean is an instance of "shadow RMIConnectorServer", and its58constructor has a parameter of type "shadow JMXServiceURL". If the59constructor is invoked with "real JMXServiceURL" it will fail.6061While we are at it, we also test that the behaviour is correct for62the JMXMP protocol, if that optional protocol is present.63*/64import java.lang.reflect.*;65import java.net.*;66import java.util.*;67import javax.management.*;68import javax.management.loading.*;69import javax.management.remote.*;70import javax.management.remote.rmi.RMIConnectorServer;7172public class TargetMBeanTest {73private static final ObjectName mletName;74static {75try {76mletName = new ObjectName("x:type=mlet");77} catch (Exception e) {78e.printStackTrace();79throw new Error();80}81}8283public static void main(String[] args) throws Exception {84System.out.println("Test that target MBean class loader is used " +85"before JMX Remote API class loader");8687ClassLoader jmxRemoteClassLoader =88JMXServiceURL.class.getClassLoader();89if (jmxRemoteClassLoader == null) {90System.out.println("JMX Remote API loaded by bootstrap " +91"class loader, this test is irrelevant");92return;93}94if (!(jmxRemoteClassLoader instanceof URLClassLoader)) {95System.out.println("TEST INVALID: JMX Remote API not loaded by " +96"URLClassLoader");97System.exit(1);98}99100URLClassLoader jrcl = (URLClassLoader) jmxRemoteClassLoader;101URL[] urls = jrcl.getURLs();102PrivateMLet mlet = new PrivateMLet(urls, null, false);103Class shadowClass = mlet.loadClass(JMXServiceURL.class.getName());104if (shadowClass == JMXServiceURL.class) {105System.out.println("TEST INVALID: MLet got original " +106"JMXServiceURL not shadow");107System.exit(1);108}109110MBeanServer mbs = MBeanServerFactory.newMBeanServer();111mbs.registerMBean(mlet, mletName);112113final String[] protos = {"rmi", "iiop", "jmxmp"};114boolean ok = true;115for (int i = 0; i < protos.length; i++) {116try {117ok &= test(protos[i], mbs);118} catch (Exception e) {119System.out.println("TEST FAILED WITH EXCEPTION:");120e.printStackTrace(System.out);121ok = false;122}123}124125if (ok)126System.out.println("Test passed");127else {128System.out.println("TEST FAILED");129System.exit(1);130}131}132133private static boolean test(String proto, MBeanServer mbs)134throws Exception {135System.out.println("Testing for proto " + proto);136137JMXConnectorServer cs;138JMXServiceURL url = new JMXServiceURL(proto, null, 0);139try {140cs = JMXConnectorServerFactory.newJMXConnectorServer(url, null,141mbs);142} catch (MalformedURLException e) {143System.out.println("System does not recognize URL: " + url +144"; ignoring");145return true;146}147cs.start();148JMXServiceURL addr = cs.getAddress();149JMXServiceURL rmiurl = new JMXServiceURL("rmi", null, 0);150JMXConnector client = JMXConnectorFactory.connect(addr);151MBeanServerConnection mbsc = client.getMBeanServerConnection();152ObjectName on = new ObjectName("x:proto=" + proto + ",ok=yes");153mbsc.createMBean(RMIConnectorServer.class.getName(),154on,155mletName,156new Object[] {rmiurl, null},157new String[] {JMXServiceURL.class.getName(),158Map.class.getName()});159System.out.println("Successfully deserialized with " + proto);160mbsc.unregisterMBean(on);161162client.close();163cs.stop();164return true;165}166}167168169