8173607: JMX RMI connector should be in its own module
authordfuchs
Thu, 02 Feb 2017 16:50:46 +0000
changeset 43503 bc7f8619ab70
parent 43502 aec39566b45e
child 43504 937634498e8c
child 43505 dbb07ad63c71
8173607: JMX RMI connector should be in its own module Summary: The JMX RMI connector is moved to a new java.management.rmi module. Reviewed-by: mchung, erikj
jdk/make/rmic/Rmic-java.management.gmk
jdk/make/rmic/Rmic-java.management.rmi.gmk
jdk/src/java.base/share/classes/module-info.java
jdk/src/java.management.rmi/share/classes/com/sun/jmx/remote/internal/rmi/ProxyRef.java
jdk/src/java.management.rmi/share/classes/com/sun/jmx/remote/internal/rmi/RMIExporter.java
jdk/src/java.management.rmi/share/classes/com/sun/jmx/remote/internal/rmi/Unmarshal.java
jdk/src/java.management.rmi/share/classes/com/sun/jmx/remote/protocol/rmi/ClientProvider.java
jdk/src/java.management.rmi/share/classes/com/sun/jmx/remote/protocol/rmi/ServerProvider.java
jdk/src/java.management.rmi/share/classes/javax/management/remote/rmi/NoCallStackClassLoader.java
jdk/src/java.management.rmi/share/classes/javax/management/remote/rmi/RMIConnection.java
jdk/src/java.management.rmi/share/classes/javax/management/remote/rmi/RMIConnectionImpl.java
jdk/src/java.management.rmi/share/classes/javax/management/remote/rmi/RMIConnector.java
jdk/src/java.management.rmi/share/classes/javax/management/remote/rmi/RMIConnectorServer.java
jdk/src/java.management.rmi/share/classes/javax/management/remote/rmi/RMIIIOPServerImpl.java
jdk/src/java.management.rmi/share/classes/javax/management/remote/rmi/RMIJRMPServerImpl.java
jdk/src/java.management.rmi/share/classes/javax/management/remote/rmi/RMIServer.java
jdk/src/java.management.rmi/share/classes/javax/management/remote/rmi/RMIServerImpl.java
jdk/src/java.management.rmi/share/classes/javax/management/remote/rmi/package.html
jdk/src/java.management.rmi/share/classes/module-info.java
jdk/src/java.management/share/classes/com/sun/jmx/remote/internal/ClientNotifForwarder.java
jdk/src/java.management/share/classes/com/sun/jmx/remote/internal/ProxyRef.java
jdk/src/java.management/share/classes/com/sun/jmx/remote/internal/RMIExporter.java
jdk/src/java.management/share/classes/com/sun/jmx/remote/internal/Unmarshal.java
jdk/src/java.management/share/classes/com/sun/jmx/remote/protocol/rmi/ClientProvider.java
jdk/src/java.management/share/classes/com/sun/jmx/remote/protocol/rmi/ServerProvider.java
jdk/src/java.management/share/classes/javax/management/remote/JMXConnectorFactory.java
jdk/src/java.management/share/classes/javax/management/remote/JMXConnectorServerFactory.java
jdk/src/java.management/share/classes/javax/management/remote/rmi/NoCallStackClassLoader.java
jdk/src/java.management/share/classes/javax/management/remote/rmi/RMIConnection.java
jdk/src/java.management/share/classes/javax/management/remote/rmi/RMIConnectionImpl.java
jdk/src/java.management/share/classes/javax/management/remote/rmi/RMIConnector.java
jdk/src/java.management/share/classes/javax/management/remote/rmi/RMIConnectorServer.java
jdk/src/java.management/share/classes/javax/management/remote/rmi/RMIIIOPServerImpl.java
jdk/src/java.management/share/classes/javax/management/remote/rmi/RMIJRMPServerImpl.java
jdk/src/java.management/share/classes/javax/management/remote/rmi/RMIServer.java
jdk/src/java.management/share/classes/javax/management/remote/rmi/RMIServerImpl.java
jdk/src/java.management/share/classes/javax/management/remote/rmi/package.html
jdk/src/java.management/share/classes/module-info.java
jdk/src/java.rmi/share/classes/module-info.java
jdk/src/java.se/share/classes/module-info.java
jdk/src/jdk.jconsole/share/classes/module-info.java
jdk/src/jdk.management.agent/share/classes/module-info.java
jdk/src/jdk.management.agent/share/classes/sun/management/jmxremote/ConnectorBootstrap.java
jdk/test/javax/management/MBeanInfo/NotificationInfoTest.java
jdk/test/javax/management/MBeanServer/ExceptionTest.java
jdk/test/javax/management/MBeanServer/OldMBeanServerTest.java
jdk/test/javax/management/modelmbean/UnserializableTargetObjectTest.java
jdk/test/javax/management/mxbean/GenericArrayTypeTest.java
jdk/test/javax/management/mxbean/MXBeanExceptionHandlingTest.java
jdk/test/javax/management/mxbean/MXBeanInteropTest1.java
jdk/test/javax/management/mxbean/MXBeanInteropTest2.java
jdk/test/javax/management/mxbean/MXBeanNotifTest.java
jdk/test/javax/management/mxbean/MXBeanTest.java
jdk/test/javax/management/mxbean/MXBeanWeirdParamTest.java
jdk/test/javax/management/query/SupportedQueryTypesTest.java
jdk/test/javax/management/remote/mandatory/connection/AddressableTest.java
jdk/test/javax/management/remote/mandatory/connection/BrokenConnectionTest.java
jdk/test/javax/management/remote/mandatory/connection/CloseableTest.java
jdk/test/javax/management/remote/mandatory/connection/ConnectionListenerNullTest.java
jdk/test/javax/management/remote/mandatory/connection/ConnectionTest.java
jdk/test/javax/management/remote/mandatory/connection/DaemonRMIExporterTest.java
jdk/test/javax/management/remote/mandatory/connection/GetConnectionTest.java
jdk/test/javax/management/remote/mandatory/connection/IIOPURLTest.java
jdk/test/javax/management/remote/mandatory/connection/IdleTimeoutTest.java
jdk/test/javax/management/remote/mandatory/connection/MultiThreadDeadLockTest.java
jdk/test/javax/management/remote/mandatory/connection/ObjectInputStreamWithLoaderNullCheckTest.java
jdk/test/javax/management/remote/mandatory/connection/RMIConnectorInternalMapTest.java
jdk/test/javax/management/remote/mandatory/connection/RMIConnectorNullSubjectConnTest.java
jdk/test/javax/management/remote/mandatory/connection/RMIConnector_NPETest.java
jdk/test/javax/management/remote/mandatory/connection/RMIExitTest.java
jdk/test/javax/management/remote/mandatory/connection/RMISerializeTest.java
jdk/test/javax/management/remote/mandatory/connectorServer/ConnectorStopDeadlockTest.java
jdk/test/javax/management/remote/mandatory/connectorServer/JNDIFailureTest.java
jdk/test/javax/management/remote/mandatory/connectorServer/MBSFPreStartPostStartTest.java
jdk/test/javax/management/remote/mandatory/connectorServer/RMIExporterTest.java
jdk/test/javax/management/remote/mandatory/connectorServer/SetMBeanServerForwarder.java
jdk/test/javax/management/remote/mandatory/loading/DeserializeEncodedURLTest.java
jdk/test/javax/management/remote/mandatory/loading/MissingClassTest.java
jdk/test/javax/management/remote/mandatory/loading/RMIDownloadTest.java
jdk/test/javax/management/remote/mandatory/loading/TargetMBeanTest.java
jdk/test/javax/management/remote/mandatory/notif/ConcurrentModificationTest.java
jdk/test/javax/management/remote/mandatory/notif/DeadListenerTest.java
jdk/test/javax/management/remote/mandatory/notif/EmptyDomainNotificationTest.java
jdk/test/javax/management/remote/mandatory/notif/ListenerScaleTest.java
jdk/test/javax/management/remote/mandatory/notif/NotSerializableNotifTest.java
jdk/test/javax/management/remote/mandatory/notif/NotifReconnectDeadlockTest.java
jdk/test/javax/management/remote/mandatory/notif/NotificationAccessControllerTest.java
jdk/test/javax/management/remote/mandatory/notif/NotificationBufferCreationTest.java
jdk/test/javax/management/remote/mandatory/notif/NotificationEmissionTest.java
jdk/test/javax/management/remote/mandatory/notif/RMINotifTest.java
jdk/test/javax/management/remote/mandatory/notif/ServerNotifs.java
jdk/test/javax/management/remote/mandatory/notif/UnexpectedNotifTest.java
jdk/test/javax/management/remote/mandatory/passwordAccessFile/NonJMXPrincipalsTest.java
jdk/test/javax/management/remote/mandatory/passwordAccessFile/PasswordAccessFileTest.java
jdk/test/javax/management/remote/mandatory/passwordAuthenticator/RMIAltAuthTest.java
jdk/test/javax/management/remote/mandatory/passwordAuthenticator/RMIPasswdAuthTest.java
jdk/test/javax/management/remote/mandatory/provider/ProviderTest.java
jdk/test/javax/management/remote/mandatory/serverError/JMXServerErrorTest.java
jdk/test/javax/management/remote/mandatory/socketFactories/RMISocketFactoriesTest.java
jdk/test/javax/management/remote/mandatory/subjectDelegation/SubjectDelegation1Test.java
jdk/test/javax/management/remote/mandatory/subjectDelegation/SubjectDelegation2Test.java
jdk/test/javax/management/remote/mandatory/subjectDelegation/SubjectDelegation3Test.java
jdk/test/javax/management/remote/mandatory/util/MapNullValuesTest.java
jdk/test/javax/management/security/AuthorizationTest.java
jdk/test/javax/management/security/SecurityTest.java
jdk/test/sun/management/jmxremote/bootstrap/TestManager.java
jdk/test/tools/launcher/modules/listmods/ListModsTest.java
--- a/jdk/make/rmic/Rmic-java.management.gmk	Thu Feb 02 12:28:23 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-#
-# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.  Oracle designates this
-# particular file as subject to the "Classpath" exception as provided
-# by Oracle in the LICENSE file that accompanied this code.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-default: all
-
-include RmicCommon.gmk
-
-##########################################################################################
-#
-# Generate RMI stubs
-#
-
-JMX_RMI_CLASSES := javax.management.remote.rmi.RMIConnectionImpl \
-    javax.management.remote.rmi.RMIServerImpl
-
-# Generate into gensrc dir where sources get picked up for javadoc, then move the classes
-# into the stub classes dir.
-$(eval $(call SetupRMICompilation,RMI_GEN, \
-    CLASSES := $(JMX_RMI_CLASSES), \
-    CLASSES_DIR := $(CLASSES_DIR)/java.management, \
-    STUB_CLASSES_DIR := $(RMIC_GENSRC_DIR)/java.management, \
-    RUN_V12 := true, \
-    KEEP_GENERATED := true, \
-))
-
-# Find all classes generated and move them from the gensrc dir to the stub classes dir
-$(RMIC_GENSRC_DIR)/_classes.moved: $(RMI_GEN)
-	$(eval classfiles := $(shell $(FIND) $(RMIC_GENSRC_DIR) -name "*.class"))
-	$(foreach src, $(classfiles), \
-	    $(eval target := $(patsubst $(RMIC_GENSRC_DIR)/%, \
-	        $(STUB_CLASSES_DIR)/%, $(src))) \
-	    $(MKDIR) -p $(dir $(target)) ; \
-	    $(MV) $(src) $(target) $(NEWLINE))
-	$(TOUCH) $@
-
-##########################################################################################
-
-all: $(RMIC_GENSRC_DIR)/_classes.moved $(RMI_GEN)
-
-.PHONY: all
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/rmic/Rmic-java.management.rmi.gmk	Thu Feb 02 16:50:46 2017 +0000
@@ -0,0 +1,62 @@
+#
+# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+default: all
+
+include RmicCommon.gmk
+
+##########################################################################################
+#
+# Generate RMI stubs
+#
+
+JMX_RMI_CLASSES := javax.management.remote.rmi.RMIConnectionImpl \
+    javax.management.remote.rmi.RMIServerImpl
+
+# Generate into gensrc dir where sources get picked up for javadoc, then move the classes
+# into the stub classes dir.
+$(eval $(call SetupRMICompilation,RMI_GEN, \
+    CLASSES := $(JMX_RMI_CLASSES), \
+    CLASSES_DIR := $(CLASSES_DIR)/java.management.rmi, \
+    STUB_CLASSES_DIR := $(RMIC_GENSRC_DIR)/java.management.rmi, \
+    RUN_V12 := true, \
+    KEEP_GENERATED := true, \
+))
+
+# Find all classes generated and move them from the gensrc dir to the stub classes dir
+$(RMIC_GENSRC_DIR)/_classes.moved: $(RMI_GEN)
+	$(eval classfiles := $(shell $(FIND) $(RMIC_GENSRC_DIR) -name "*.class"))
+	$(foreach src, $(classfiles), \
+	    $(eval target := $(patsubst $(RMIC_GENSRC_DIR)/%, \
+	        $(STUB_CLASSES_DIR)/%, $(src))) \
+	    $(MKDIR) -p $(dir $(target)) ; \
+	    $(MV) $(src) $(target) $(NEWLINE))
+	$(TOUCH) $@
+
+##########################################################################################
+
+all: $(RMIC_GENSRC_DIR)/_classes.moved $(RMI_GEN)
+
+.PHONY: all
--- a/jdk/src/java.base/share/classes/module-info.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/src/java.base/share/classes/module-info.java	Thu Feb 02 16:50:46 2017 +0000
@@ -150,7 +150,7 @@
         java.desktop;
     exports jdk.internal.module to
         java.instrument,
-        java.management,
+        java.management.rmi,
         jdk.jartool,
         jdk.jlink;
     exports jdk.internal.misc to
@@ -235,6 +235,7 @@
         java.desktop,
         java.datatransfer,
         java.management,
+        java.management.rmi,
         java.rmi,
         java.sql.rowset,
         java.xml,
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.management.rmi/share/classes/com/sun/jmx/remote/internal/rmi/ProxyRef.java	Thu Feb 02 16:50:46 2017 +0000
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.jmx.remote.internal.rmi;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.lang.reflect.Method;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.rmi.server.RemoteObject;
+import java.rmi.server.RemoteRef;
+
+
+@SuppressWarnings("deprecation")
+public class ProxyRef implements RemoteRef {
+    private static final long serialVersionUID = -6503061366316814723L;
+
+    public ProxyRef(RemoteRef ref) {
+        this.ref = ref;
+    }
+
+    public void readExternal(ObjectInput in)
+            throws IOException, ClassNotFoundException {
+        ref.readExternal(in);
+    }
+
+    public void writeExternal(ObjectOutput out) throws IOException {
+        ref.writeExternal(out);
+    }
+
+    /**
+     * @deprecated
+     */
+    @Deprecated
+    public void invoke(java.rmi.server.RemoteCall call) throws Exception {
+        ref.invoke(call);
+    }
+
+    public Object invoke(Remote obj, Method method, Object[] params,
+                         long opnum) throws Exception {
+        return ref.invoke(obj, method, params, opnum);
+    }
+
+    /**
+     * @deprecated
+     */
+    @Deprecated
+    public void done(java.rmi.server.RemoteCall call) throws RemoteException {
+        ref.done(call);
+    }
+
+    public String getRefClass(ObjectOutput out) {
+        return ref.getRefClass(out);
+    }
+
+    /**
+     * @deprecated
+     */
+    @Deprecated
+    public java.rmi.server.RemoteCall newCall(RemoteObject obj,
+            java.rmi.server.Operation[] op, int opnum,
+                              long hash) throws RemoteException {
+        return ref.newCall(obj, op, opnum, hash);
+    }
+
+    public boolean remoteEquals(RemoteRef obj) {
+        return ref.remoteEquals(obj);
+    }
+
+    public int remoteHashCode() {
+        return ref.remoteHashCode();
+    }
+
+    public String remoteToString() {
+        return ref.remoteToString();
+    }
+
+    protected RemoteRef ref;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.management.rmi/share/classes/com/sun/jmx/remote/internal/rmi/RMIExporter.java	Thu Feb 02 16:50:46 2017 +0000
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.jmx.remote.internal.rmi;
+
+import java.rmi.NoSuchObjectException;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.rmi.server.RMIClientSocketFactory;
+import java.rmi.server.RMIServerSocketFactory;
+import java.rmi.server.UnicastRemoteObject;
+
+/**
+ * <p>Unpublished interface controlling how the RMI Connector Server
+ * exports objects.  The RMIServerImpl object and each
+ * RMIConnectionImpl object are exported using the exporter.  The
+ * default exporter calls {@link
+ * UnicastRemoteObject#exportObject(Remote, int,
+ * RMIClientSocketFactory, RMIServerSocketFactory)} to export objects
+ * and {@link UnicastRemoteObject#unexportObject(Remote, boolean)} to
+ * unexport them.  A replacement exporter can be specified via the
+ * {@link #EXPORTER_ATTRIBUTE} property in the environment Map passed
+ * to the RMI connector server.</p>
+ */
+public interface RMIExporter {
+    public static final String EXPORTER_ATTRIBUTE =
+        "com.sun.jmx.remote.rmi.exporter";
+
+    public Remote exportObject(Remote obj,
+                               int port,
+                               RMIClientSocketFactory csf,
+                               RMIServerSocketFactory ssf)
+            throws RemoteException;
+
+    public boolean unexportObject(Remote obj, boolean force)
+            throws NoSuchObjectException;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.management.rmi/share/classes/com/sun/jmx/remote/internal/rmi/Unmarshal.java	Thu Feb 02 16:50:46 2017 +0000
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.jmx.remote.internal.rmi;
+
+import java.io.IOException;
+import java.rmi.MarshalledObject;
+
+public interface Unmarshal {
+    public Object get(MarshalledObject<?> mo)
+            throws IOException, ClassNotFoundException;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.management.rmi/share/classes/com/sun/jmx/remote/protocol/rmi/ClientProvider.java	Thu Feb 02 16:50:46 2017 +0000
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2002, 2004, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.jmx.remote.protocol.rmi;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.util.Map;
+
+import javax.management.remote.JMXConnectorProvider;
+import javax.management.remote.JMXConnector;
+import javax.management.remote.JMXServiceURL;
+import javax.management.remote.rmi.RMIConnector;
+
+public class ClientProvider implements JMXConnectorProvider {
+
+    public JMXConnector newJMXConnector(JMXServiceURL serviceURL,
+                                        Map<String,?> environment)
+            throws IOException {
+        if (!serviceURL.getProtocol().equals("rmi")) {
+            throw new MalformedURLException("Protocol not rmi: " +
+                                            serviceURL.getProtocol());
+        }
+        return new RMIConnector(serviceURL, environment);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.management.rmi/share/classes/com/sun/jmx/remote/protocol/rmi/ServerProvider.java	Thu Feb 02 16:50:46 2017 +0000
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.jmx.remote.protocol.rmi;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.util.Map;
+
+import javax.management.MBeanServer;
+import javax.management.remote.JMXConnectorServer;
+import javax.management.remote.JMXConnectorServerProvider;
+import javax.management.remote.JMXServiceURL;
+import javax.management.remote.rmi.RMIConnectorServer;
+
+public class ServerProvider implements JMXConnectorServerProvider {
+
+    public JMXConnectorServer newJMXConnectorServer(JMXServiceURL serviceURL,
+                                                    Map<String,?> environment,
+                                                    MBeanServer mbeanServer)
+            throws IOException {
+        if (!serviceURL.getProtocol().equals("rmi")) {
+            throw new MalformedURLException("Protocol not rmi: " +
+                                            serviceURL.getProtocol());
+        }
+        return new RMIConnectorServer(serviceURL, environment, mbeanServer);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.management.rmi/share/classes/javax/management/remote/rmi/NoCallStackClassLoader.java	Thu Feb 02 16:50:46 2017 +0000
@@ -0,0 +1,296 @@
+/*
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package javax.management.remote.rmi;
+
+import java.security.ProtectionDomain;
+
+/**
+    <p>A class loader that only knows how to define a limited number
+    of classes, and load a limited number of other classes through
+    delegation to another loader.  It is used to get around a problem
+    with Serialization, in particular as used by RMI. The JMX Remote API
+    defines exactly what class loader must be used to deserialize arguments on
+    the server, and return values on the client.  We communicate this class
+    loader to RMI by setting it as the context class loader.  RMI uses the
+    context class loader to load classes as it deserializes, which is what we
+    want.  However, before consulting the context class loader, it
+    looks up the call stack for a class with a non-null class loader,
+    and uses that if it finds one.  So, in the standalone version of
+    javax.management.remote, if the class you're looking for is known
+    to the loader of jmxremote.jar (typically the system class loader)
+    then that loader will load it.  This contradicts the class-loading
+    semantics required.
+
+    <p>We get around the problem by ensuring that the search up the
+    call stack will find a non-null class loader that doesn't load any
+    classes of interest, namely this one.  So even though this loader
+    is indeed consulted during deserialization, it never finds the
+    class being deserialized.  RMI then proceeds to use the context
+    class loader, as we require.
+
+    <p>This loader is constructed with the name and byte-code of one
+    or more classes that it defines, and a class-loader to which it
+    will delegate certain other classes required by that byte-code.
+    We construct the byte-code somewhat painstakingly, by compiling
+    the Java code directly, converting into a string, copying that
+    string into the class that needs this loader, and using the
+    stringToBytes method to convert it into the byte array.  We
+    compile with -g:none because there's not much point in having
+    line-number information and the like in these directly-encoded
+    classes.
+
+    <p>The referencedClassNames should contain the names of all
+    classes that are referenced by the classes defined by this loader.
+    It is not necessary to include standard J2SE classes, however.
+    Here, a class is referenced if it is the superclass or a
+    superinterface of a defined class, or if it is the type of a
+    field, parameter, or return value.  A class is not referenced if
+    it only appears in the throws clause of a method or constructor.
+    Of course, referencedClassNames should not contain any classes
+    that the user might want to deserialize, because the whole point
+    of this loader is that it does not find such classes.
+*/
+
+class NoCallStackClassLoader extends ClassLoader {
+    /** Simplified constructor when this loader only defines one class.  */
+    public NoCallStackClassLoader(String className,
+                                  byte[] byteCode,
+                                  String[] referencedClassNames,
+                                  ClassLoader referencedClassLoader,
+                                  ProtectionDomain protectionDomain) {
+        this(new String[] {className}, new byte[][] {byteCode},
+             referencedClassNames, referencedClassLoader, protectionDomain);
+    }
+
+    public NoCallStackClassLoader(String[] classNames,
+                                  byte[][] byteCodes,
+                                  String[] referencedClassNames,
+                                  ClassLoader referencedClassLoader,
+                                  ProtectionDomain protectionDomain) {
+        super(null);
+
+        /* Validation. */
+        if (classNames == null || classNames.length == 0
+            || byteCodes == null || classNames.length != byteCodes.length
+            || referencedClassNames == null || protectionDomain == null)
+            throw new IllegalArgumentException();
+        for (int i = 0; i < classNames.length; i++) {
+            if (classNames[i] == null || byteCodes[i] == null)
+                throw new IllegalArgumentException();
+        }
+        for (int i = 0; i < referencedClassNames.length; i++) {
+            if (referencedClassNames[i] == null)
+                throw new IllegalArgumentException();
+        }
+
+        this.classNames = classNames;
+        this.byteCodes = byteCodes;
+        this.referencedClassNames = referencedClassNames;
+        this.referencedClassLoader = referencedClassLoader;
+        this.protectionDomain = protectionDomain;
+    }
+
+    /* This method is called at most once per name.  Define the name
+     * if it is one of the classes whose byte code we have, or
+     * delegate the load if it is one of the referenced classes.
+     */
+    @Override
+    protected Class<?> findClass(String name) throws ClassNotFoundException {
+        // Note: classNames is guaranteed by the constructor to be non-null.
+        for (int i = 0; i < classNames.length; i++) {
+            if (name.equals(classNames[i])) {
+                return defineClass(classNames[i], byteCodes[i], 0,
+                                   byteCodes[i].length, protectionDomain);
+            }
+        }
+
+        /* If the referencedClassLoader is null, it is the bootstrap
+         * class loader, and there's no point in delegating to it
+         * because it's already our parent class loader.
+         */
+        if (referencedClassLoader != null) {
+            for (int i = 0; i < referencedClassNames.length; i++) {
+                if (name.equals(referencedClassNames[i]))
+                    return referencedClassLoader.loadClass(name);
+            }
+        }
+
+        throw new ClassNotFoundException(name);
+    }
+
+    private final String[] classNames;
+    private final byte[][] byteCodes;
+    private final String[] referencedClassNames;
+    private final ClassLoader referencedClassLoader;
+    private final ProtectionDomain protectionDomain;
+
+    /**
+     * <p>Construct a <code>byte[]</code> using the characters of the
+     * given <code>String</code>.  Only the low-order byte of each
+     * character is used.  This method is useful to reduce the
+     * footprint of classes that include big byte arrays (e.g. the
+     * byte code of other classes), because a string takes up much
+     * less space in a class file than the byte code to initialize a
+     * <code>byte[]</code> with the same number of bytes.</p>
+     *
+     * <p>We use just one byte per character even though characters
+     * contain two bytes.  The resultant output length is much the
+     * same: using one byte per character is shorter because it has
+     * more characters in the optimal 1-127 range but longer because
+     * it has more zero bytes (which are frequent, and are encoded as
+     * two bytes in classfile UTF-8).  But one byte per character has
+     * two key advantages: (1) you can see the string constants, which
+     * is reassuring, (2) you don't need to know whether the class
+     * file length is odd.</p>
+     *
+     * <p>This method differs from {@link String#getBytes()} in that
+     * it does not use any encoding.  So it is guaranteed that each
+     * byte of the result is numerically identical (mod 256) to the
+     * corresponding character of the input.
+     */
+    public static byte[] stringToBytes(String s) {
+        final int slen = s.length();
+        byte[] bytes = new byte[slen];
+        for (int i = 0; i < slen; i++)
+            bytes[i] = (byte) s.charAt(i);
+        return bytes;
+    }
+}
+
+/*
+
+You can use the following Emacs function to convert class files into
+strings to be used by the stringToBytes method above.  Select the
+whole (defun...) with the mouse and type M-x eval-region, or save it
+to a file and do M-x load-file.  Then visit the *.class file and do
+M-x class-string.
+
+;; class-string.el
+;; visit the *.class file with emacs, then invoke this function
+
+(defun class-string ()
+  "Construct a Java string whose bytes are the same as the current
+buffer.  The resultant string is put in a buffer called *string*,
+possibly with a numeric suffix like <2>.  From there it can be
+insert-buffer'd into a Java program."
+  (interactive)
+  (let* ((s (buffer-string))
+         (slen (length s))
+         (i 0)
+         (buf (generate-new-buffer "*string*")))
+    (set-buffer buf)
+    (insert "\"")
+    (while (< i slen)
+      (if (> (current-column) 61)
+          (insert "\"+\n\""))
+      (let ((c (aref s i)))
+        (insert (cond
+                 ((> c 126) (format "\\%o" c))
+                 ((= c ?\") "\\\"")
+                 ((= c ?\\) "\\\\")
+                 ((< c 33)
+                  (let ((nextc (if (< (1+ i) slen)
+                                   (aref s (1+ i))
+                                 ?\0)))
+                    (cond
+                     ((and (<= nextc ?7) (>= nextc ?0))
+                      (format "\\%03o" c))
+                     (t
+                      (format "\\%o" c)))))
+                 (t c))))
+      (setq i (1+ i)))
+    (insert "\"")
+    (switch-to-buffer buf)))
+
+Alternatively, the following class reads a class file and outputs a string
+that can be used by the stringToBytes method above.
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+
+public class BytesToString {
+
+    public static void main(String[] args) throws IOException {
+        File f = new File(args[0]);
+        int len = (int)f.length();
+        byte[] classBytes = new byte[len];
+
+        FileInputStream in = new FileInputStream(args[0]);
+        try {
+            int pos = 0;
+            for (;;) {
+                int n = in.read(classBytes, pos, (len-pos));
+                if (n < 0)
+                    throw new RuntimeException("class file changed??");
+                pos += n;
+                if (pos >= n)
+                    break;
+            }
+        } finally {
+            in.close();
+        }
+
+        int pos = 0;
+        boolean lastWasOctal = false;
+        for (int i=0; i<len; i++) {
+            int value = classBytes[i];
+            if (value < 0)
+                value += 256;
+            String s = null;
+            if (value == '\\')
+                s = "\\\\";
+            else if (value == '\"')
+                s = "\\\"";
+            else {
+                if ((value >= 32 && value < 127) && ((!lastWasOctal ||
+                    (value < '0' || value > '7')))) {
+                    s = Character.toString((char)value);
+                }
+            }
+            if (s == null) {
+                s = "\\" + Integer.toString(value, 8);
+                lastWasOctal = true;
+            } else {
+                lastWasOctal = false;
+            }
+            if (pos > 61) {
+                System.out.print("\"");
+                if (i<len)
+                    System.out.print("+");
+                System.out.println();
+                pos = 0;
+            }
+            if (pos == 0)
+                System.out.print("                \"");
+            System.out.print(s);
+            pos += s.length();
+        }
+        System.out.println("\"");
+    }
+}
+
+*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.management.rmi/share/classes/javax/management/remote/rmi/RMIConnection.java	Thu Feb 02 16:50:46 2017 +0000
@@ -0,0 +1,1092 @@
+/*
+ * Copyright (c) 2002, 2008, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package javax.management.remote.rmi;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.rmi.MarshalledObject;
+import java.rmi.Remote;
+import java.util.Set;
+
+import javax.management.AttributeList;
+import javax.management.AttributeNotFoundException;
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.InstanceNotFoundException;
+import javax.management.IntrospectionException;
+import javax.management.InvalidAttributeValueException;
+import javax.management.ListenerNotFoundException;
+import javax.management.MBeanException;
+import javax.management.MBeanInfo;
+import javax.management.MBeanRegistrationException;
+import javax.management.MBeanServerConnection;
+import javax.management.NotCompliantMBeanException;
+
+import javax.management.ObjectInstance;
+import javax.management.ObjectName;
+import javax.management.ReflectionException;
+import javax.management.RuntimeMBeanException;
+import javax.management.RuntimeOperationsException;
+import javax.management.remote.NotificationResult;
+import javax.security.auth.Subject;
+
+/**
+ * <p>RMI object used to forward an MBeanServer request from a client
+ * to its MBeanServer implementation on the server side.  There is one
+ * Remote object implementing this interface for each remote client
+ * connected to an RMI connector.</p>
+ *
+ * <p>User code does not usually refer to this interface.  It is
+ * specified as part of the public API so that different
+ * implementations of that API will interoperate.</p>
+ *
+ * <p>To ensure that client parameters will be deserialized at the
+ * server side with the correct classloader, client parameters such as
+ * parameters used to invoke a method are wrapped in a {@link
+ * MarshalledObject}.  An implementation of this interface must first
+ * get the appropriate class loader for the operation and its target,
+ * then deserialize the marshalled parameters with this classloader.
+ * Except as noted, a parameter that is a
+ * <code>MarshalledObject</code> or <code>MarshalledObject[]</code>
+ * must not be null; the behavior is unspecified if it is.</p>
+ *
+ * <p>Class loading aspects are detailed in the
+ * <a href="{@docRoot}/../technotes/guides/jmx/JMX_1_4_specification.pdf">
+ * JMX Specification, version 1.4</a> PDF document.</p>
+ *
+ * <p>Most methods in this interface parallel methods in the {@link
+ * MBeanServerConnection} interface.  Where an aspect of the behavior
+ * of a method is not specified here, it is the same as in the
+ * corresponding <code>MBeanServerConnection</code> method.
+ *
+ * @since 1.5
+ */
+/*
+ * Notice that we omit the type parameter from MarshalledObject everywhere,
+ * even though it would add useful information to the documentation.  The
+ * reason is that it was only added in Mustang (Java SE 6), whereas versions
+ * 1.4 and 2.0 of the JMX API must be implementable on Tiger per our
+ * commitments for JSR 255.  This is also why we suppress rawtypes warnings.
+ */
+@SuppressWarnings("rawtypes")
+public interface RMIConnection extends Closeable, Remote {
+    /**
+     * <p>Returns the connection ID.  This string is different for
+     * every open connection to a given RMI connector server.</p>
+     *
+     * @return the connection ID
+     *
+     * @see RMIConnector#connect RMIConnector.connect
+     *
+     * @throws IOException if a general communication exception occurred.
+     */
+    public String getConnectionId() throws IOException;
+
+    /**
+     * <p>Closes this connection.  On return from this method, the RMI
+     * object implementing this interface is unexported, so further
+     * remote calls to it will fail.</p>
+     *
+     * @throws IOException if the connection could not be closed,
+     * or the Remote object could not be unexported, or there was a
+     * communication failure when transmitting the remote close
+     * request.
+     */
+    public void close() throws IOException;
+
+    /**
+     * Handles the method {@link
+     * javax.management.MBeanServerConnection#createMBean(String,
+     * ObjectName)}.
+     *
+     * @param className The class name of the MBean to be instantiated.
+     * @param name The object name of the MBean. May be null.
+     * @param delegationSubject The <code>Subject</code> containing the
+     * delegation principals or <code>null</code> if the authentication
+     * principal is used instead.
+     *
+     * @return An <code>ObjectInstance</code>, containing the
+     * <code>ObjectName</code> and the Java class name of the newly
+     * instantiated MBean.  If the contained <code>ObjectName</code>
+     * is <code>n</code>, the contained Java class name is
+     * <code>{@link #getMBeanInfo getMBeanInfo(n)}.getClassName()</code>.
+     *
+     * @throws ReflectionException Wraps a
+     * <code>java.lang.ClassNotFoundException</code> or a
+     * <code>java.lang.Exception</code> that occurred
+     * when trying to invoke the MBean's constructor.
+     * @throws InstanceAlreadyExistsException The MBean is already
+     * under the control of the MBean server.
+     * @throws MBeanRegistrationException The
+     * <code>preRegister</code> (<code>MBeanRegistration</code>
+     * interface) method of the MBean has thrown an exception. The
+     * MBean will not be registered.
+     * @throws MBeanException The constructor of the MBean has
+     * thrown an exception.
+     * @throws NotCompliantMBeanException This class is not a JMX
+     * compliant MBean.
+     * @throws RuntimeOperationsException Wraps a
+     * <code>java.lang.IllegalArgumentException</code>: The className
+     * passed in parameter is null, the <code>ObjectName</code> passed
+     * in parameter contains a pattern or no <code>ObjectName</code>
+     * is specified for the MBean.
+     * @throws SecurityException if the client, or the delegated Subject
+     * if any, does not have permission to perform this operation.
+     * @throws IOException if a general communication exception occurred.
+     */
+    public ObjectInstance createMBean(String className,
+                                      ObjectName name,
+                                      Subject delegationSubject)
+        throws
+        ReflectionException,
+        InstanceAlreadyExistsException,
+        MBeanRegistrationException,
+        MBeanException,
+        NotCompliantMBeanException,
+        IOException;
+
+    /**
+     * Handles the method {@link
+     * javax.management.MBeanServerConnection#createMBean(String,
+     * ObjectName, ObjectName)}.
+     *
+     * @param className The class name of the MBean to be instantiated.
+     * @param name The object name of the MBean. May be null.
+     * @param loaderName The object name of the class loader to be used.
+     * @param delegationSubject The <code>Subject</code> containing the
+     * delegation principals or <code>null</code> if the authentication
+     * principal is used instead.
+     *
+     * @return An <code>ObjectInstance</code>, containing the
+     * <code>ObjectName</code> and the Java class name of the newly
+     * instantiated MBean.  If the contained <code>ObjectName</code>
+     * is <code>n</code>, the contained Java class name is
+     * <code>{@link #getMBeanInfo getMBeanInfo(n)}.getClassName()</code>.
+     *
+     * @throws ReflectionException Wraps a
+     * <code>java.lang.ClassNotFoundException</code> or a
+     * <code>java.lang.Exception</code> that occurred when trying to
+     * invoke the MBean's constructor.
+     * @throws InstanceAlreadyExistsException The MBean is already
+     * under the control of the MBean server.
+     * @throws MBeanRegistrationException The
+     * <code>preRegister</code> (<code>MBeanRegistration</code>
+     * interface) method of the MBean has thrown an exception. The
+     * MBean will not be registered.
+     * @throws MBeanException The constructor of the MBean has
+     * thrown an exception.
+     * @throws NotCompliantMBeanException This class is not a JMX
+     * compliant MBean.
+     * @throws InstanceNotFoundException The specified class loader
+     * is not registered in the MBean server.
+     * @throws RuntimeOperationsException Wraps a
+     * <code>java.lang.IllegalArgumentException</code>: The className
+     * passed in parameter is null, the <code>ObjectName</code> passed
+     * in parameter contains a pattern or no <code>ObjectName</code>
+     * is specified for the MBean.
+     * @throws SecurityException if the client, or the delegated Subject
+     * if any, does not have permission to perform this operation.
+     * @throws IOException if a general communication exception occurred.
+     */
+    public ObjectInstance createMBean(String className,
+                                      ObjectName name,
+                                      ObjectName loaderName,
+                                      Subject delegationSubject)
+        throws
+        ReflectionException,
+        InstanceAlreadyExistsException,
+        MBeanRegistrationException,
+        MBeanException,
+        NotCompliantMBeanException,
+        InstanceNotFoundException,
+        IOException;
+
+    /**
+     * Handles the method {@link
+     * javax.management.MBeanServerConnection#createMBean(String,
+     * ObjectName, Object[], String[])}.  The <code>Object[]</code>
+     * parameter is wrapped in a <code>MarshalledObject</code>.
+     *
+     * @param className The class name of the MBean to be instantiated.
+     * @param name The object name of the MBean. May be null.
+     * @param params An array containing the parameters of the
+     * constructor to be invoked, encapsulated into a
+     * <code>MarshalledObject</code>.  The encapsulated array can be
+     * null, equivalent to an empty array.
+     * @param signature An array containing the signature of the
+     * constructor to be invoked.  Can be null, equivalent to an empty
+     * array.
+     * @param delegationSubject The <code>Subject</code> containing the
+     * delegation principals or <code>null</code> if the authentication
+     * principal is used instead.
+     *
+     * @return An <code>ObjectInstance</code>, containing the
+     * <code>ObjectName</code> and the Java class name of the newly
+     * instantiated MBean.  If the contained <code>ObjectName</code>
+     * is <code>n</code>, the contained Java class name is
+     * <code>{@link #getMBeanInfo getMBeanInfo(n)}.getClassName()</code>.
+     *
+     * @throws ReflectionException Wraps a
+     * <code>java.lang.ClassNotFoundException</code> or a
+     * <code>java.lang.Exception</code> that occurred when trying to
+     * invoke the MBean's constructor.
+     * @throws InstanceAlreadyExistsException The MBean is already
+     * under the control of the MBean server.
+     * @throws MBeanRegistrationException The
+     * <code>preRegister</code> (<code>MBeanRegistration</code>
+     * interface) method of the MBean has thrown an exception. The
+     * MBean will not be registered.
+     * @throws MBeanException The constructor of the MBean has
+     * thrown an exception.
+     * @throws NotCompliantMBeanException This class is not a JMX
+     * compliant MBean.
+     * @throws RuntimeOperationsException Wraps a
+     * <code>java.lang.IllegalArgumentException</code>: The className
+     * passed in parameter is null, the <code>ObjectName</code> passed
+     * in parameter contains a pattern, or no <code>ObjectName</code>
+     * is specified for the MBean.
+     * @throws SecurityException if the client, or the delegated Subject
+     * if any, does not have permission to perform this operation.
+     * @throws IOException if a general communication exception occurred.
+     */
+    public ObjectInstance createMBean(String className,
+                                ObjectName name,
+                                MarshalledObject params,
+                                String signature[],
+                                Subject delegationSubject)
+        throws
+        ReflectionException,
+        InstanceAlreadyExistsException,
+        MBeanRegistrationException,
+        MBeanException,
+        NotCompliantMBeanException,
+        IOException;
+
+    /**
+     * Handles the method {@link
+     * javax.management.MBeanServerConnection#createMBean(String,
+     * ObjectName, ObjectName, Object[], String[])}.  The
+     * <code>Object[]</code> parameter is wrapped in a
+     * <code>MarshalledObject</code>.
+     *
+     * @param className The class name of the MBean to be instantiated.
+     * @param name The object name of the MBean. May be null.
+     * @param loaderName The object name of the class loader to be used.
+     * @param params An array containing the parameters of the
+     * constructor to be invoked, encapsulated into a
+     * <code>MarshalledObject</code>.  The encapsulated array can be
+     * null, equivalent to an empty array.
+     * @param signature An array containing the signature of the
+     * constructor to be invoked.  Can be null, equivalent to an empty
+     * array.
+     * @param delegationSubject The <code>Subject</code> containing the
+     * delegation principals or <code>null</code> if the authentication
+     * principal is used instead.
+     *
+     * @return An <code>ObjectInstance</code>, containing the
+     * <code>ObjectName</code> and the Java class name of the newly
+     * instantiated MBean.  If the contained <code>ObjectName</code>
+     * is <code>n</code>, the contained Java class name is
+     * <code>{@link #getMBeanInfo getMBeanInfo(n)}.getClassName()</code>.
+     *
+     * @throws ReflectionException Wraps a
+     * <code>java.lang.ClassNotFoundException</code> or a
+     * <code>java.lang.Exception</code> that occurred when trying to
+     * invoke the MBean's constructor.
+     * @throws InstanceAlreadyExistsException The MBean is already
+     * under the control of the MBean server.
+     * @throws MBeanRegistrationException The
+     * <code>preRegister</code> (<code>MBeanRegistration</code>
+     * interface) method of the MBean has thrown an exception. The
+     * MBean will not be registered.
+     * @throws MBeanException The constructor of the MBean has
+     * thrown an exception.
+     * @throws NotCompliantMBeanException This class is not a JMX
+     * compliant MBean.
+     * @throws InstanceNotFoundException The specified class loader
+     * is not registered in the MBean server.
+     * @throws RuntimeOperationsException Wraps a
+     * <code>java.lang.IllegalArgumentException</code>: The className
+     * passed in parameter is null, the <code>ObjectName</code> passed
+     * in parameter contains a pattern, or no <code>ObjectName</code>
+     * is specified for the MBean.
+     * @throws SecurityException if the client, or the delegated Subject
+     * if any, does not have permission to perform this operation.
+     * @throws IOException if a general communication exception occurred.
+     */
+    public ObjectInstance createMBean(String className,
+                                ObjectName name,
+                                ObjectName loaderName,
+                                MarshalledObject params,
+                                String signature[],
+                                Subject delegationSubject)
+        throws
+        ReflectionException,
+        InstanceAlreadyExistsException,
+        MBeanRegistrationException,
+        MBeanException,
+        NotCompliantMBeanException,
+        InstanceNotFoundException,
+        IOException;
+
+    /**
+     * Handles the method
+     * {@link javax.management.MBeanServerConnection#unregisterMBean(ObjectName)}.
+     *
+     * @param name The object name of the MBean to be unregistered.
+     * @param delegationSubject The <code>Subject</code> containing the
+     * delegation principals or <code>null</code> if the authentication
+     * principal is used instead.
+     *
+     * @throws InstanceNotFoundException The MBean specified is not
+     * registered in the MBean server.
+     * @throws MBeanRegistrationException The preDeregister
+     * ((<code>MBeanRegistration</code> interface) method of the MBean
+     * has thrown an exception.
+     * @throws RuntimeOperationsException Wraps a
+     * <code>java.lang.IllegalArgumentException</code>: The object
+     * name in parameter is null or the MBean you are when trying to
+     * unregister is the {@link javax.management.MBeanServerDelegate
+     * MBeanServerDelegate} MBean.
+     * @throws SecurityException if the client, or the delegated Subject
+     * if any, does not have permission to perform this operation.
+     * @throws IOException if a general communication exception occurred.
+     */
+    public void unregisterMBean(ObjectName name, Subject delegationSubject)
+        throws
+        InstanceNotFoundException,
+        MBeanRegistrationException,
+        IOException;
+
+    /**
+     * Handles the method
+     * {@link javax.management.MBeanServerConnection#getObjectInstance(ObjectName)}.
+     *
+     * @param name The object name of the MBean.
+     * @param delegationSubject The <code>Subject</code> containing the
+     * delegation principals or <code>null</code> if the authentication
+     * principal is used instead.
+     *
+     * @return The <code>ObjectInstance</code> associated with the MBean
+     * specified by <var>name</var>.  The contained <code>ObjectName</code>
+     * is <code>name</code> and the contained class name is
+     * <code>{@link #getMBeanInfo getMBeanInfo(name)}.getClassName()</code>.
+     *
+     * @throws InstanceNotFoundException The MBean specified is not
+     * registered in the MBean server.
+     * @throws RuntimeOperationsException Wraps a
+     * <code>java.lang.IllegalArgumentException</code>: The object
+     * name in parameter is null.
+     * @throws SecurityException if the client, or the delegated Subject
+     * if any, does not have permission to perform this operation.
+     * @throws IOException if a general communication exception occurred.
+     */
+    public ObjectInstance getObjectInstance(ObjectName name,
+                                            Subject delegationSubject)
+        throws InstanceNotFoundException, IOException;
+
+    /**
+     * Handles the method {@link
+     * javax.management.MBeanServerConnection#queryMBeans(ObjectName,
+     * QueryExp)}.  The <code>QueryExp</code> is wrapped in a
+     * <code>MarshalledObject</code>.
+     *
+     * @param name The object name pattern identifying the MBeans to
+     * be retrieved. If null or no domain and key properties are
+     * specified, all the MBeans registered will be retrieved.
+     * @param query The query expression to be applied for selecting
+     * MBeans, encapsulated into a <code>MarshalledObject</code>. If
+     * the <code>MarshalledObject</code> encapsulates a null value no
+     * query expression will be applied for selecting MBeans.
+     * @param delegationSubject The <code>Subject</code> containing the
+     * delegation principals or <code>null</code> if the authentication
+     * principal is used instead.
+     *
+     * @return A set containing the <code>ObjectInstance</code>
+     * objects for the selected MBeans.  If no MBean satisfies the
+     * query an empty list is returned.
+     *
+     * @throws SecurityException if the client, or the delegated Subject
+     * if any, does not have permission to perform this operation.
+     * @throws IOException if a general communication exception occurred.
+     */
+    public Set<ObjectInstance>
+        queryMBeans(ObjectName name,
+                    MarshalledObject query,
+                    Subject delegationSubject)
+        throws IOException;
+
+    /**
+     * Handles the method {@link
+     * javax.management.MBeanServerConnection#queryNames(ObjectName,
+     * QueryExp)}.  The <code>QueryExp</code> is wrapped in a
+     * <code>MarshalledObject</code>.
+     *
+     * @param name The object name pattern identifying the MBean names
+     * to be retrieved. If null or no domain and key properties are
+     * specified, the name of all registered MBeans will be retrieved.
+     * @param query The query expression to be applied for selecting
+     * MBeans, encapsulated into a <code>MarshalledObject</code>. If
+     * the <code>MarshalledObject</code> encapsulates a null value no
+     * query expression will be applied for selecting MBeans.
+     * @param delegationSubject The <code>Subject</code> containing the
+     * delegation principals or <code>null</code> if the authentication
+     * principal is used instead.
+     *
+     * @return A set containing the ObjectNames for the MBeans
+     * selected.  If no MBean satisfies the query, an empty list is
+     * returned.
+     *
+     * @throws SecurityException if the client, or the delegated Subject
+     * if any, does not have permission to perform this operation.
+     * @throws IOException if a general communication exception occurred.
+     */
+    public Set<ObjectName>
+        queryNames(ObjectName name,
+                   MarshalledObject query,
+                   Subject delegationSubject)
+        throws IOException;
+
+    /**
+     * Handles the method
+     * {@link javax.management.MBeanServerConnection#isRegistered(ObjectName)}.
+     *
+     * @param name The object name of the MBean to be checked.
+     * @param delegationSubject The <code>Subject</code> containing the
+     * delegation principals or <code>null</code> if the authentication
+     * principal is used instead.
+     *
+     * @return True if the MBean is already registered in the MBean
+     * server, false otherwise.
+     *
+     * @throws RuntimeOperationsException Wraps a
+     * <code>java.lang.IllegalArgumentException</code>: The object
+     * name in parameter is null.
+     * @throws SecurityException if the client, or the delegated Subject
+     * if any, does not have permission to perform this operation.
+     * @throws IOException if a general communication exception occurred.
+     */
+    public boolean isRegistered(ObjectName name, Subject delegationSubject)
+        throws IOException;
+
+    /**
+     * Handles the method
+     * {@link javax.management.MBeanServerConnection#getMBeanCount()}.
+     *
+     * @param delegationSubject The <code>Subject</code> containing the
+     * delegation principals or <code>null</code> if the authentication
+     * principal is used instead.
+     *
+     * @return the number of MBeans registered.
+     *
+     * @throws SecurityException if the client, or the delegated Subject
+     * if any, does not have permission to perform this operation.
+     * @throws IOException if a general communication exception occurred.
+     */
+    public Integer getMBeanCount(Subject delegationSubject)
+        throws IOException;
+
+    /**
+     * Handles the method {@link
+     * javax.management.MBeanServerConnection#getAttribute(ObjectName,
+     * String)}.
+     *
+     * @param name The object name of the MBean from which the
+     * attribute is to be retrieved.
+     * @param attribute A String specifying the name of the attribute
+     * to be retrieved.
+     * @param delegationSubject The <code>Subject</code> containing the
+     * delegation principals or <code>null</code> if the authentication
+     * principal is used instead.
+     *
+     * @return  The value of the retrieved attribute.
+     *
+     * @throws AttributeNotFoundException The attribute specified
+     * is not accessible in the MBean.
+     * @throws MBeanException Wraps an exception thrown by the
+     * MBean's getter.
+     * @throws InstanceNotFoundException The MBean specified is not
+     * registered in the MBean server.
+     * @throws ReflectionException Wraps a
+     * <code>java.lang.Exception</code> thrown when trying to invoke
+     * the getter.
+     * @throws RuntimeOperationsException Wraps a
+     * <code>java.lang.IllegalArgumentException</code>: The object
+     * name in parameter is null or the attribute in parameter is
+     * null.
+     * @throws RuntimeMBeanException Wraps a runtime exception thrown
+     * by the MBean's getter.
+     * @throws SecurityException if the client, or the delegated Subject
+     * if any, does not have permission to perform this operation.
+     * @throws IOException if a general communication exception occurred.
+     *
+     * @see #setAttribute
+     */
+    public Object getAttribute(ObjectName name,
+                               String attribute,
+                               Subject delegationSubject)
+        throws
+        MBeanException,
+        AttributeNotFoundException,
+        InstanceNotFoundException,
+        ReflectionException,
+        IOException;
+
+    /**
+     * Handles the method {@link
+     * javax.management.MBeanServerConnection#getAttributes(ObjectName,
+     * String[])}.
+     *
+     * @param name The object name of the MBean from which the
+     * attributes are retrieved.
+     * @param attributes A list of the attributes to be retrieved.
+     * @param delegationSubject The <code>Subject</code> containing the
+     * delegation principals or <code>null</code> if the authentication
+     * principal is used instead.
+     *
+     * @return The list of the retrieved attributes.
+     *
+     * @throws InstanceNotFoundException The MBean specified is not
+     * registered in the MBean server.
+     * @throws ReflectionException An exception occurred when
+     * trying to invoke the getAttributes method of a Dynamic MBean.
+     * @throws RuntimeOperationsException Wrap a
+     * <code>java.lang.IllegalArgumentException</code>: The object
+     * name in parameter is null or attributes in parameter is null.
+     * @throws SecurityException if the client, or the delegated Subject
+     * if any, does not have permission to perform this operation.
+     * @throws IOException if a general communication exception occurred.
+     *
+     * @see #setAttributes
+     */
+    public AttributeList getAttributes(ObjectName name,
+                                       String[] attributes,
+                                       Subject delegationSubject)
+        throws
+        InstanceNotFoundException,
+        ReflectionException,
+        IOException;
+
+    /**
+     * Handles the method {@link
+     * javax.management.MBeanServerConnection#setAttribute(ObjectName,
+     * Attribute)}.  The <code>Attribute</code> parameter is wrapped
+     * in a <code>MarshalledObject</code>.
+     *
+     * @param name The name of the MBean within which the attribute is
+     * to be set.
+     * @param attribute The identification of the attribute to be set
+     * and the value it is to be set to, encapsulated into a
+     * <code>MarshalledObject</code>.
+     * @param delegationSubject The <code>Subject</code> containing the
+     * delegation principals or <code>null</code> if the authentication
+     * principal is used instead.
+     *
+     * @throws InstanceNotFoundException The MBean specified is not
+     * registered in the MBean server.
+     * @throws AttributeNotFoundException The attribute specified
+     * is not accessible in the MBean.
+     * @throws InvalidAttributeValueException The value specified
+     * for the attribute is not valid.
+     * @throws MBeanException Wraps an exception thrown by the
+     * MBean's setter.
+     * @throws ReflectionException Wraps a
+     * <code>java.lang.Exception</code> thrown when trying to invoke
+     * the setter.
+     * @throws RuntimeOperationsException Wraps a
+     * <code>java.lang.IllegalArgumentException</code>: The object
+     * name in parameter is null or the attribute in parameter is
+     * null.
+     * @throws SecurityException if the client, or the delegated Subject
+     * if any, does not have permission to perform this operation.
+     * @throws IOException if a general communication exception occurred.
+     *
+     * @see #getAttribute
+     */
+    public void setAttribute(ObjectName name,
+                             MarshalledObject attribute,
+                             Subject delegationSubject)
+        throws
+        InstanceNotFoundException,
+        AttributeNotFoundException,
+        InvalidAttributeValueException,
+        MBeanException,
+        ReflectionException,
+        IOException;
+
+    /**
+     * Handles the method {@link
+     * javax.management.MBeanServerConnection#setAttributes(ObjectName,
+     * AttributeList)}.  The <code>AttributeList</code> parameter is
+     * wrapped in a <code>MarshalledObject</code>.
+     *
+     * @param name The object name of the MBean within which the
+     * attributes are to be set.
+     * @param attributes A list of attributes: The identification of
+     * the attributes to be set and the values they are to be set to,
+     * encapsulated into a <code>MarshalledObject</code>.
+     * @param delegationSubject The <code>Subject</code> containing the
+     * delegation principals or <code>null</code> if the authentication
+     * principal is used instead.
+     *
+     * @return The list of attributes that were set, with their new
+     * values.
+     *
+     * @throws InstanceNotFoundException The MBean specified is not
+     * registered in the MBean server.
+     * @throws ReflectionException An exception occurred when
+     * trying to invoke the getAttributes method of a Dynamic MBean.
+     * @throws RuntimeOperationsException Wraps a
+     * <code>java.lang.IllegalArgumentException</code>: The object
+     * name in parameter is null or attributes in parameter is null.
+     * @throws SecurityException if the client, or the delegated Subject
+     * if any, does not have permission to perform this operation.
+     * @throws IOException if a general communication exception occurred.
+     *
+     * @see #getAttributes
+     */
+    public AttributeList setAttributes(ObjectName name,
+                          MarshalledObject attributes,
+                          Subject delegationSubject)
+        throws
+        InstanceNotFoundException,
+        ReflectionException,
+        IOException;
+
+    /**
+     * Handles the method {@link
+     * javax.management.MBeanServerConnection#invoke(ObjectName,
+     * String, Object[], String[])}.  The <code>Object[]</code>
+     * parameter is wrapped in a <code>MarshalledObject</code>.
+     *
+     * @param name The object name of the MBean on which the method is
+     * to be invoked.
+     * @param operationName The name of the operation to be invoked.
+     * @param params An array containing the parameters to be set when
+     * the operation is invoked, encapsulated into a
+     * <code>MarshalledObject</code>.  The encapsulated array can be
+     * null, equivalent to an empty array.
+     * @param signature An array containing the signature of the
+     * operation. The class objects will be loaded using the same
+     * class loader as the one used for loading the MBean on which the
+     * operation was invoked.  Can be null, equivalent to an empty
+     * array.
+     * @param delegationSubject The <code>Subject</code> containing the
+     * delegation principals or <code>null</code> if the authentication
+     * principal is used instead.
+     *
+     * @return The object returned by the operation, which represents
+     * the result of invoking the operation on the MBean specified.
+     *
+     * @throws InstanceNotFoundException The MBean specified is not
+     * registered in the MBean server.
+     * @throws MBeanException Wraps an exception thrown by the
+     * MBean's invoked method.
+     * @throws ReflectionException Wraps a
+     * <code>java.lang.Exception</code> thrown while trying to invoke
+     * the method.
+     * @throws SecurityException if the client, or the delegated Subject
+     * if any, does not have permission to perform this operation.
+     * @throws IOException if a general communication exception occurred.
+     * @throws RuntimeOperationsException Wraps an {@link
+     * IllegalArgumentException} when <code>name</code> or
+     * <code>operationName</code> is null.
+     */
+    public Object invoke(ObjectName name,
+                         String operationName,
+                         MarshalledObject params,
+                         String signature[],
+                         Subject delegationSubject)
+        throws
+        InstanceNotFoundException,
+        MBeanException,
+        ReflectionException,
+        IOException;
+
+    /**
+     * Handles the method
+     * {@link javax.management.MBeanServerConnection#getDefaultDomain()}.
+     *
+     * @param delegationSubject The <code>Subject</code> containing the
+     * delegation principals or <code>null</code> if the authentication
+     * principal is used instead.
+     *
+     * @return the default domain.
+     *
+     * @throws SecurityException if the client, or the delegated Subject
+     * if any, does not have permission to perform this operation.
+     * @throws IOException if a general communication exception occurred.
+     */
+    public String getDefaultDomain(Subject delegationSubject)
+        throws IOException;
+
+    /**
+     * Handles the method
+     * {@link javax.management.MBeanServerConnection#getDomains()}.
+     *
+     * @param delegationSubject The <code>Subject</code> containing the
+     * delegation principals or <code>null</code> if the authentication
+     * principal is used instead.
+     *
+     * @return the list of domains.
+     *
+     * @throws SecurityException if the client, or the delegated Subject
+     * if any, does not have permission to perform this operation.
+     * @throws IOException if a general communication exception occurred.
+     */
+    public String[] getDomains(Subject delegationSubject)
+        throws IOException;
+
+    /**
+     * Handles the method
+     * {@link javax.management.MBeanServerConnection#getMBeanInfo(ObjectName)}.
+     *
+     * @param name The name of the MBean to analyze
+     * @param delegationSubject The <code>Subject</code> containing the
+     * delegation principals or <code>null</code> if the authentication
+     * principal is used instead.
+     *
+     * @return An instance of <code>MBeanInfo</code> allowing the
+     * retrieval of all attributes and operations of this MBean.
+     *
+     * @throws IntrospectionException An exception occurred during
+     * introspection.
+     * @throws InstanceNotFoundException The MBean specified was
+     * not found.
+     * @throws ReflectionException An exception occurred when
+     * trying to invoke the getMBeanInfo of a Dynamic MBean.
+     * @throws SecurityException if the client, or the delegated Subject
+     * if any, does not have permission to perform this operation.
+     * @throws IOException if a general communication exception occurred.
+     * @throws RuntimeOperationsException Wraps a
+     * <code>java.lang.IllegalArgumentException</code>: The object
+     * name in parameter is null.
+     */
+    public MBeanInfo getMBeanInfo(ObjectName name, Subject delegationSubject)
+        throws
+        InstanceNotFoundException,
+        IntrospectionException,
+        ReflectionException,
+        IOException;
+
+    /**
+     * Handles the method {@link
+     * javax.management.MBeanServerConnection#isInstanceOf(ObjectName,
+     * String)}.
+     *
+     * @param name The <code>ObjectName</code> of the MBean.
+     * @param className The name of the class.
+     * @param delegationSubject The <code>Subject</code> containing the
+     * delegation principals or <code>null</code> if the authentication
+     * principal is used instead.
+     *
+     * @return true if the MBean specified is an instance of the
+     * specified class according to the rules above, false otherwise.
+     *
+     * @throws InstanceNotFoundException The MBean specified is not
+     * registered in the MBean server.
+     * @throws SecurityException if the client, or the delegated Subject
+     * if any, does not have permission to perform this operation.
+     * @throws IOException if a general communication exception occurred.
+     * @throws RuntimeOperationsException Wraps a
+     * <code>java.lang.IllegalArgumentException</code>: The object
+     * name in parameter is null.
+     */
+    public boolean isInstanceOf(ObjectName name,
+                                String className,
+                                Subject delegationSubject)
+        throws InstanceNotFoundException, IOException;
+
+    /**
+     * Handles the method {@link
+     * javax.management.MBeanServerConnection#addNotificationListener(ObjectName,
+     * ObjectName, NotificationFilter, Object)}.  The
+     * <code>NotificationFilter</code> parameter is wrapped in a
+     * <code>MarshalledObject</code>.  The <code>Object</code>
+     * (handback) parameter is also wrapped in a
+     * <code>MarshalledObject</code>.
+     *
+     * @param name The name of the MBean on which the listener should
+     * be added.
+     * @param listener The object name of the listener which will
+     * handle the notifications emitted by the registered MBean.
+     * @param filter The filter object, encapsulated into a
+     * <code>MarshalledObject</code>. If filter encapsulated in the
+     * <code>MarshalledObject</code> has a null value, no filtering
+     * will be performed before handling notifications.
+     * @param handback The context to be sent to the listener when a
+     * notification is emitted, encapsulated into a
+     * <code>MarshalledObject</code>.
+     * @param delegationSubject The <code>Subject</code> containing the
+     * delegation principals or <code>null</code> if the authentication
+     * principal is used instead.
+     *
+     * @throws InstanceNotFoundException The MBean name of the
+     * notification listener or of the notification broadcaster does
+     * not match any of the registered MBeans.
+     * @throws RuntimeOperationsException Wraps an {@link
+     * IllegalArgumentException}.  The MBean named by
+     * <code>listener</code> exists but does not implement the
+     * {@link javax.management.NotificationListener} interface,
+     * or <code>name</code> or <code>listener</code> is null.
+     * @throws SecurityException if the client, or the delegated Subject
+     * if any, does not have permission to perform this operation.
+     * @throws IOException if a general communication exception occurred.
+     *
+     * @see #removeNotificationListener(ObjectName, ObjectName, Subject)
+     * @see #removeNotificationListener(ObjectName, ObjectName,
+     * MarshalledObject, MarshalledObject, Subject)
+     */
+    public void addNotificationListener(ObjectName name,
+                        ObjectName listener,
+                        MarshalledObject filter,
+                        MarshalledObject handback,
+                        Subject delegationSubject)
+        throws InstanceNotFoundException, IOException;
+
+    /**
+     * Handles the method {@link
+     * javax.management.MBeanServerConnection#removeNotificationListener(ObjectName,
+     * ObjectName)}.
+     *
+     * @param name The name of the MBean on which the listener should
+     * be removed.
+     * @param listener The object name of the listener to be removed.
+     * @param delegationSubject The <code>Subject</code> containing the
+     * delegation principals or <code>null</code> if the authentication
+     * principal is used instead.
+     *
+     * @throws InstanceNotFoundException The MBean name provided
+     * does not match any of the registered MBeans.
+     * @throws ListenerNotFoundException The listener is not
+     * registered in the MBean.
+     * @throws SecurityException if the client, or the delegated Subject
+     * if any, does not have permission to perform this operation.
+     * @throws IOException if a general communication exception occurred.
+     * @throws RuntimeOperationsException Wraps an {@link
+     * IllegalArgumentException} when <code>name</code> or
+     * <code>listener</code> is null.
+     *
+     * @see #addNotificationListener
+     */
+    public void removeNotificationListener(ObjectName name,
+                                           ObjectName listener,
+                                           Subject delegationSubject)
+        throws
+        InstanceNotFoundException,
+        ListenerNotFoundException,
+        IOException;
+
+    /**
+     * Handles the method {@link
+     * javax.management.MBeanServerConnection#removeNotificationListener(ObjectName,
+     * ObjectName, NotificationFilter, Object)}.  The
+     * <code>NotificationFilter</code> parameter is wrapped in a
+     * <code>MarshalledObject</code>.  The <code>Object</code>
+     * parameter is also wrapped in a <code>MarshalledObject</code>.
+     *
+     * @param name The name of the MBean on which the listener should
+     * be removed.
+     * @param listener A listener that was previously added to this
+     * MBean.
+     * @param filter The filter that was specified when the listener
+     * was added, encapsulated into a <code>MarshalledObject</code>.
+     * @param handback The handback that was specified when the
+     * listener was added, encapsulated into a <code>MarshalledObject</code>.
+     * @param delegationSubject The <code>Subject</code> containing the
+     * delegation principals or <code>null</code> if the authentication
+     * principal is used instead.
+     *
+     * @throws InstanceNotFoundException The MBean name provided
+     * does not match any of the registered MBeans.
+     * @throws ListenerNotFoundException The listener is not
+     * registered in the MBean, or it is not registered with the given
+     * filter and handback.
+     * @throws SecurityException if the client, or the delegated Subject
+     * if any, does not have permission to perform this operation.
+     * @throws IOException if a general communication exception occurred.
+     * @throws RuntimeOperationsException Wraps an {@link
+     * IllegalArgumentException} when <code>name</code> or
+     * <code>listener</code> is null.
+     *
+     * @see #addNotificationListener
+     */
+    public void removeNotificationListener(ObjectName name,
+                      ObjectName listener,
+                      MarshalledObject filter,
+                      MarshalledObject handback,
+                      Subject delegationSubject)
+        throws
+        InstanceNotFoundException,
+        ListenerNotFoundException,
+        IOException;
+
+    // Special Handling of Notifications -------------------------------------
+
+    /**
+     * <p>Handles the method {@link
+     * javax.management.MBeanServerConnection#addNotificationListener(ObjectName,
+     * NotificationListener, NotificationFilter, Object)}.</p>
+     *
+     * <p>Register for notifications from the given MBeans that match
+     * the given filters.  The remote client can subsequently retrieve
+     * the notifications using the {@link #fetchNotifications
+     * fetchNotifications} method.</p>
+     *
+     * <p>For each listener, the original
+     * <code>NotificationListener</code> and <code>handback</code> are
+     * kept on the client side; in order for the client to be able to
+     * identify them, the server generates and returns a unique
+     * <code>listenerID</code>.  This <code>listenerID</code> is
+     * forwarded with the <code>Notifications</code> to the remote
+     * client.</p>
+     *
+     * <p>If any one of the given (name, filter) pairs cannot be
+     * registered, then the operation fails with an exception, and no
+     * names or filters are registered.</p>
+     *
+     * @param names the <code>ObjectNames</code> identifying the
+     * MBeans emitting the Notifications.
+     * @param filters an array of marshalled representations of the
+     * <code>NotificationFilters</code>.  Elements of this array can
+     * be null.
+     * @param delegationSubjects the <code>Subjects</code> on behalf
+     * of which the listeners are being added.  Elements of this array
+     * can be null.  Also, the <code>delegationSubjects</code>
+     * parameter itself can be null, which is equivalent to an array
+     * of null values with the same size as the <code>names</code> and
+     * <code>filters</code> arrays.
+     *
+     * @return an array of <code>listenerIDs</code> identifying the
+     * local listeners.  This array has the same number of elements as
+     * the parameters.
+     *
+     * @throws IllegalArgumentException if <code>names</code> or
+     * <code>filters</code> is null, or if <code>names</code> contains
+     * a null element, or if the three arrays do not all have the same
+     * size.
+     * @throws ClassCastException if one of the elements of
+     * <code>filters</code> unmarshalls as a non-null object that is
+     * not a <code>NotificationFilter</code>.
+     * @throws InstanceNotFoundException if one of the
+     * <code>names</code> does not correspond to any registered MBean.
+     * @throws SecurityException if, for one of the MBeans, the
+     * client, or the delegated Subject if any, does not have
+     * permission to add a listener.
+     * @throws IOException if a general communication exception occurred.
+     */
+    public Integer[] addNotificationListeners(ObjectName[] names,
+                    MarshalledObject[] filters,
+                    Subject[] delegationSubjects)
+        throws InstanceNotFoundException, IOException;
+
+    /**
+     * <p>Handles the
+     * {@link javax.management.MBeanServerConnection#removeNotificationListener(ObjectName,NotificationListener)
+     * removeNotificationListener(ObjectName, NotificationListener)} and
+     * {@link javax.management.MBeanServerConnection#removeNotificationListener(ObjectName,NotificationListener,NotificationFilter,Object)
+     * removeNotificationListener(ObjectName, NotificationListener, NotificationFilter, Object)} methods.</p>
+     *
+     * <p>This method removes one or more
+     * <code>NotificationListener</code>s from a given MBean in the
+     * MBean server.</p>
+     *
+     * <p>The <code>NotificationListeners</code> are identified by the
+     * IDs which were returned by the {@link
+     * #addNotificationListeners(ObjectName[], MarshalledObject[],
+     * Subject[])} method.</p>
+     *
+     * @param name the <code>ObjectName</code> identifying the MBean
+     * emitting the Notifications.
+     * @param listenerIDs the list of the IDs corresponding to the
+     * listeners to remove.
+     * @param delegationSubject The <code>Subject</code> containing the
+     * delegation principals or <code>null</code> if the authentication
+     * principal is used instead.
+     *
+     * @throws InstanceNotFoundException if the given
+     * <code>name</code> does not correspond to any registered MBean.
+     * @throws ListenerNotFoundException if one of the listeners was
+     * not found on the server side.  This exception can happen if the
+     * MBean discarded a listener for some reason other than a call to
+     * <code>MBeanServer.removeNotificationListener</code>.
+     * @throws SecurityException if the client, or the delegated Subject
+     * if any, does not have permission to remove the listeners.
+     * @throws IOException if a general communication exception occurred.
+     * @throws IllegalArgumentException if <code>ObjectName</code> or
+     * <code>listenerIds</code> is null or if <code>listenerIds</code>
+     * contains a null element.
+     */
+    public void removeNotificationListeners(ObjectName name,
+                                            Integer[] listenerIDs,
+                                            Subject delegationSubject)
+        throws
+        InstanceNotFoundException,
+        ListenerNotFoundException,
+        IOException;
+
+    /**
+     * <p>Retrieves notifications from the connector server.  This
+     * method can block until there is at least one notification or
+     * until the specified timeout is reached.  The method can also
+     * return at any time with zero notifications.</p>
+     *
+     * <p>A notification can be included in the result if its sequence
+     * number is no less than <code>clientSequenceNumber</code> and
+     * this client has registered at least one listener for the MBean
+     * generating the notification, with a filter that accepts the
+     * notification.  Each listener that is interested in the
+     * notification is identified by an Integer ID that was returned
+     * by {@link #addNotificationListeners(ObjectName[],
+     * MarshalledObject[], Subject[])}.</p>
+     *
+     * @param clientSequenceNumber the first sequence number that the
+     * client is interested in.  If negative, it is interpreted as
+     * meaning the sequence number that the next notification will
+     * have.
+     *
+     * @param maxNotifications the maximum number of different
+     * notifications to return.  The <code>TargetedNotification</code>
+     * array in the returned <code>NotificationResult</code> can have
+     * more elements than this if the same notification appears more
+     * than once.  The behavior is unspecified if this parameter is
+     * negative.
+     *
+     * @param timeout the maximum time in milliseconds to wait for a
+     * notification to arrive.  This can be 0 to indicate that the
+     * method should not wait if there are no notifications, but
+     * should return at once.  It can be <code>Long.MAX_VALUE</code>
+     * to indicate that there is no timeout.  The behavior is
+     * unspecified if this parameter is negative.
+     *
+     * @return A <code>NotificationResult</code>.
+     *
+     * @throws IOException if a general communication exception occurred.
+     */
+    public NotificationResult fetchNotifications(long clientSequenceNumber,
+                                                 int maxNotifications,
+                                                 long timeout)
+            throws IOException;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.management.rmi/share/classes/javax/management/remote/rmi/RMIConnectionImpl.java	Thu Feb 02 16:50:46 2017 +0000
@@ -0,0 +1,1834 @@
+/*
+ * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package javax.management.remote.rmi;
+
+import java.io.IOException;
+import java.rmi.MarshalledObject;
+import java.rmi.UnmarshalException;
+import java.rmi.server.Unreferenced;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.Permission;
+import java.security.Permissions;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.security.ProtectionDomain;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
+import javax.management.*;
+import javax.management.remote.JMXServerErrorException;
+import javax.management.remote.NotificationResult;
+import javax.security.auth.Subject;
+import sun.reflect.misc.ReflectUtil;
+
+import static javax.management.remote.rmi.RMIConnector.Util.cast;
+import com.sun.jmx.remote.internal.ServerCommunicatorAdmin;
+import com.sun.jmx.remote.internal.ServerNotifForwarder;
+import com.sun.jmx.remote.security.JMXSubjectDomainCombiner;
+import com.sun.jmx.remote.security.SubjectDelegator;
+import com.sun.jmx.remote.util.ClassLoaderWithRepository;
+import com.sun.jmx.remote.util.ClassLogger;
+import com.sun.jmx.remote.util.EnvHelp;
+import com.sun.jmx.remote.util.OrderClassLoaders;
+import javax.management.loading.ClassLoaderRepository;
+
+/**
+ * <p>Implementation of the {@link RMIConnection} interface.  User
+ * code will not usually reference this class.</p>
+ *
+ * @since 1.5
+ */
+/*
+ * Notice that we omit the type parameter from MarshalledObject everywhere,
+ * even though it would add useful information to the documentation.  The
+ * reason is that it was only added in Mustang (Java SE 6), whereas versions
+ * 1.4 and 2.0 of the JMX API must be implementable on Tiger per our
+ * commitments for JSR 255.
+ */
+public class RMIConnectionImpl implements RMIConnection, Unreferenced {
+
+    /**
+     * Constructs a new {@link RMIConnection}. This connection can be
+     * used with the JRMP transport. This object does
+     * not export itself: it is the responsibility of the caller to
+     * export it appropriately (see {@link
+     * RMIJRMPServerImpl#makeClient(String,Subject)}).
+     *
+     * @param rmiServer The RMIServerImpl object for which this
+     * connection is created.  The behavior is unspecified if this
+     * parameter is null.
+     * @param connectionId The ID for this connection.  The behavior
+     * is unspecified if this parameter is null.
+     * @param defaultClassLoader The default ClassLoader to be used
+     * when deserializing marshalled objects.  Can be null, to signify
+     * the bootstrap class loader.
+     * @param subject the authenticated subject to be used for
+     * authorization.  Can be null, to signify that no subject has
+     * been authenticated.
+     * @param env the environment containing attributes for the new
+     * <code>RMIServerImpl</code>.  Can be null, equivalent to an
+     * empty map.
+     */
+    public RMIConnectionImpl(RMIServerImpl rmiServer,
+                             String connectionId,
+                             ClassLoader defaultClassLoader,
+                             Subject subject,
+                             Map<String,?> env) {
+        if (rmiServer == null || connectionId == null)
+            throw new NullPointerException("Illegal null argument");
+        if (env == null)
+            env = Collections.emptyMap();
+        this.rmiServer = rmiServer;
+        this.connectionId = connectionId;
+        this.defaultClassLoader = defaultClassLoader;
+
+        this.subjectDelegator = new SubjectDelegator();
+        this.subject = subject;
+        if (subject == null) {
+            this.acc = null;
+            this.removeCallerContext = false;
+        } else {
+            this.removeCallerContext =
+                SubjectDelegator.checkRemoveCallerContext(subject);
+            if (this.removeCallerContext) {
+                this.acc =
+                    JMXSubjectDomainCombiner.getDomainCombinerContext(subject);
+            } else {
+                this.acc =
+                    JMXSubjectDomainCombiner.getContext(subject);
+            }
+        }
+        this.mbeanServer = rmiServer.getMBeanServer();
+
+        final ClassLoader dcl = defaultClassLoader;
+
+        ClassLoaderRepository repository = AccessController.doPrivileged(
+            new PrivilegedAction<ClassLoaderRepository>() {
+                public ClassLoaderRepository run() {
+                    return mbeanServer.getClassLoaderRepository();
+                }
+            },
+            withPermissions(new MBeanPermission("*", "getClassLoaderRepository"))
+        );
+        this.classLoaderWithRepository = AccessController.doPrivileged(
+            new PrivilegedAction<ClassLoaderWithRepository>() {
+                public ClassLoaderWithRepository run() {
+                    return new ClassLoaderWithRepository(
+                        repository,
+                        dcl);
+                }
+            },
+            withPermissions(new RuntimePermission("createClassLoader"))
+        );
+
+        this.defaultContextClassLoader =
+            AccessController.doPrivileged(
+                new PrivilegedAction<ClassLoader>() {
+            @Override
+                    public ClassLoader run() {
+                        return new CombinedClassLoader(Thread.currentThread().getContextClassLoader(),
+                                dcl);
+                    }
+                });
+
+        serverCommunicatorAdmin = new
+          RMIServerCommunicatorAdmin(EnvHelp.getServerConnectionTimeout(env));
+
+        this.env = env;
+    }
+
+    private static AccessControlContext withPermissions(Permission ... perms){
+        Permissions col = new Permissions();
+
+        for (Permission thePerm : perms ) {
+            col.add(thePerm);
+        }
+
+        final ProtectionDomain pd = new ProtectionDomain(null, col);
+        return new AccessControlContext( new ProtectionDomain[] { pd });
+    }
+
+    private synchronized ServerNotifForwarder getServerNotifFwd() {
+        // Lazily created when first use. Mainly when
+        // addNotificationListener is first called.
+        if (serverNotifForwarder == null)
+            serverNotifForwarder =
+                new ServerNotifForwarder(mbeanServer,
+                                         env,
+                                         rmiServer.getNotifBuffer(),
+                                         connectionId);
+        return serverNotifForwarder;
+    }
+
+    public String getConnectionId() throws IOException {
+        // We should call reqIncomming() here... shouldn't we?
+        return connectionId;
+    }
+
+    public void close() throws IOException {
+        final boolean debug = logger.debugOn();
+        final String  idstr = (debug?"["+this.toString()+"]":null);
+
+        synchronized (this) {
+            if (terminated) {
+                if (debug) logger.debug("close",idstr + " already terminated.");
+                return;
+            }
+
+            if (debug) logger.debug("close",idstr + " closing.");
+
+            terminated = true;
+
+            if (serverCommunicatorAdmin != null) {
+                serverCommunicatorAdmin.terminate();
+            }
+
+            if (serverNotifForwarder != null) {
+                serverNotifForwarder.terminate();
+            }
+        }
+
+        rmiServer.clientClosed(this);
+
+        if (debug) logger.debug("close",idstr + " closed.");
+    }
+
+    public void unreferenced() {
+        logger.debug("unreferenced", "called");
+        try {
+            close();
+            logger.debug("unreferenced", "done");
+        } catch (IOException e) {
+            logger.fine("unreferenced", e);
+        }
+    }
+
+    //-------------------------------------------------------------------------
+    // MBeanServerConnection Wrapper
+    //-------------------------------------------------------------------------
+
+    public ObjectInstance createMBean(String className,
+                                      ObjectName name,
+                                      Subject delegationSubject)
+        throws
+        ReflectionException,
+        InstanceAlreadyExistsException,
+        MBeanRegistrationException,
+        MBeanException,
+        NotCompliantMBeanException,
+        IOException {
+        try {
+            final Object params[] =
+                new Object[] { className, name };
+
+            if (logger.debugOn())
+                logger.debug("createMBean(String,ObjectName)",
+                             "connectionId=" + connectionId +", className=" +
+                             className+", name=" + name);
+
+            return (ObjectInstance)
+                doPrivilegedOperation(
+                  CREATE_MBEAN,
+                  params,
+                  delegationSubject);
+        } catch (PrivilegedActionException pe) {
+            Exception e = extractException(pe);
+            if (e instanceof ReflectionException)
+                throw (ReflectionException) e;
+            if (e instanceof InstanceAlreadyExistsException)
+                throw (InstanceAlreadyExistsException) e;
+            if (e instanceof MBeanRegistrationException)
+                throw (MBeanRegistrationException) e;
+            if (e instanceof MBeanException)
+                throw (MBeanException) e;
+            if (e instanceof NotCompliantMBeanException)
+                throw (NotCompliantMBeanException) e;
+            if (e instanceof IOException)
+                throw (IOException) e;
+            throw newIOException("Got unexpected server exception: " + e, e);
+        }
+    }
+
+    public ObjectInstance createMBean(String className,
+                                      ObjectName name,
+                                      ObjectName loaderName,
+                                      Subject delegationSubject)
+        throws
+        ReflectionException,
+        InstanceAlreadyExistsException,
+        MBeanRegistrationException,
+        MBeanException,
+        NotCompliantMBeanException,
+        InstanceNotFoundException,
+        IOException {
+        try {
+            final Object params[] =
+                new Object[] { className, name, loaderName };
+
+            if (logger.debugOn())
+                logger.debug("createMBean(String,ObjectName,ObjectName)",
+                      "connectionId=" + connectionId
+                      +", className=" + className
+                      +", name=" + name
+                      +", loaderName=" + loaderName);
+
+            return (ObjectInstance)
+                doPrivilegedOperation(
+                  CREATE_MBEAN_LOADER,
+                  params,
+                  delegationSubject);
+        } catch (PrivilegedActionException pe) {
+            Exception e = extractException(pe);
+            if (e instanceof ReflectionException)
+                throw (ReflectionException) e;
+            if (e instanceof InstanceAlreadyExistsException)
+                throw (InstanceAlreadyExistsException) e;
+            if (e instanceof MBeanRegistrationException)
+                throw (MBeanRegistrationException) e;
+            if (e instanceof MBeanException)
+                throw (MBeanException) e;
+            if (e instanceof NotCompliantMBeanException)
+                throw (NotCompliantMBeanException) e;
+            if (e instanceof InstanceNotFoundException)
+                throw (InstanceNotFoundException) e;
+            if (e instanceof IOException)
+                throw (IOException) e;
+            throw newIOException("Got unexpected server exception: " + e, e);
+        }
+    }
+
+    @SuppressWarnings("rawtypes")  // MarshalledObject
+    public ObjectInstance createMBean(String className,
+                                      ObjectName name,
+                                      MarshalledObject params,
+                                      String signature[],
+                                      Subject delegationSubject)
+        throws
+        ReflectionException,
+        InstanceAlreadyExistsException,
+        MBeanRegistrationException,
+        MBeanException,
+        NotCompliantMBeanException,
+        IOException {
+
+        final Object[] values;
+        final boolean debug = logger.debugOn();
+
+        if (debug) logger.debug(
+                  "createMBean(String,ObjectName,Object[],String[])",
+                  "connectionId=" + connectionId
+                  +", unwrapping parameters using classLoaderWithRepository.");
+
+        values =
+            nullIsEmpty(unwrap(params, classLoaderWithRepository, Object[].class,delegationSubject));
+
+        try {
+            final Object params2[] =
+                new Object[] { className, name, values,
+                               nullIsEmpty(signature) };
+
+            if (debug)
+               logger.debug("createMBean(String,ObjectName,Object[],String[])",
+                             "connectionId=" + connectionId
+                             +", className=" + className
+                             +", name=" + name
+                             +", signature=" + strings(signature));
+
+            return (ObjectInstance)
+                doPrivilegedOperation(
+                  CREATE_MBEAN_PARAMS,
+                  params2,
+                  delegationSubject);
+        } catch (PrivilegedActionException pe) {
+            Exception e = extractException(pe);
+            if (e instanceof ReflectionException)
+                throw (ReflectionException) e;
+            if (e instanceof InstanceAlreadyExistsException)
+                throw (InstanceAlreadyExistsException) e;
+            if (e instanceof MBeanRegistrationException)
+                throw (MBeanRegistrationException) e;
+            if (e instanceof MBeanException)
+                throw (MBeanException) e;
+            if (e instanceof NotCompliantMBeanException)
+                throw (NotCompliantMBeanException) e;
+            if (e instanceof IOException)
+                throw (IOException) e;
+            throw newIOException("Got unexpected server exception: " + e, e);
+        }
+    }
+
+    @SuppressWarnings("rawtypes")  // MarshalledObject
+    public ObjectInstance createMBean(String className,
+                                 ObjectName name,
+                                 ObjectName loaderName,
+                                 MarshalledObject params,
+                                 String signature[],
+                                 Subject delegationSubject)
+        throws
+        ReflectionException,
+        InstanceAlreadyExistsException,
+        MBeanRegistrationException,
+        MBeanException,
+        NotCompliantMBeanException,
+        InstanceNotFoundException,
+        IOException {
+
+        final Object[] values;
+        final boolean debug = logger.debugOn();
+
+        if (debug) logger.debug(
+                 "createMBean(String,ObjectName,ObjectName,Object[],String[])",
+                 "connectionId=" + connectionId
+                 +", unwrapping params with MBean extended ClassLoader.");
+
+        values = nullIsEmpty(unwrap(params,
+                                    getClassLoader(loaderName),
+                                    defaultClassLoader,
+                                    Object[].class,delegationSubject));
+
+        try {
+            final Object params2[] =
+               new Object[] { className, name, loaderName, values,
+                              nullIsEmpty(signature) };
+
+           if (debug) logger.debug(
+                 "createMBean(String,ObjectName,ObjectName,Object[],String[])",
+                 "connectionId=" + connectionId
+                 +", className=" + className
+                 +", name=" + name
+                 +", loaderName=" + loaderName
+                 +", signature=" + strings(signature));
+
+            return (ObjectInstance)
+                doPrivilegedOperation(
+                  CREATE_MBEAN_LOADER_PARAMS,
+                  params2,
+                  delegationSubject);
+        } catch (PrivilegedActionException pe) {
+            Exception e = extractException(pe);
+            if (e instanceof ReflectionException)
+                throw (ReflectionException) e;
+            if (e instanceof InstanceAlreadyExistsException)
+                throw (InstanceAlreadyExistsException) e;
+            if (e instanceof MBeanRegistrationException)
+                throw (MBeanRegistrationException) e;
+            if (e instanceof MBeanException)
+                throw (MBeanException) e;
+            if (e instanceof NotCompliantMBeanException)
+                throw (NotCompliantMBeanException) e;
+            if (e instanceof InstanceNotFoundException)
+                throw (InstanceNotFoundException) e;
+            if (e instanceof IOException)
+                throw (IOException) e;
+            throw newIOException("Got unexpected server exception: " + e, e);
+        }
+    }
+
+    public void unregisterMBean(ObjectName name, Subject delegationSubject)
+        throws
+        InstanceNotFoundException,
+        MBeanRegistrationException,
+        IOException {
+        try {
+            final Object params[] = new Object[] { name };
+
+            if (logger.debugOn()) logger.debug("unregisterMBean",
+                 "connectionId=" + connectionId
+                 +", name="+name);
+
+            doPrivilegedOperation(
+              UNREGISTER_MBEAN,
+              params,
+              delegationSubject);
+        } catch (PrivilegedActionException pe) {
+            Exception e = extractException(pe);
+            if (e instanceof InstanceNotFoundException)
+                throw (InstanceNotFoundException) e;
+            if (e instanceof MBeanRegistrationException)
+                throw (MBeanRegistrationException) e;
+            if (e instanceof IOException)
+                throw (IOException) e;
+            throw newIOException("Got unexpected server exception: " + e, e);
+        }
+    }
+
+    public ObjectInstance getObjectInstance(ObjectName name,
+                                            Subject delegationSubject)
+        throws
+        InstanceNotFoundException,
+        IOException {
+
+        checkNonNull("ObjectName", name);
+
+        try {
+            final Object params[] = new Object[] { name };
+
+            if (logger.debugOn()) logger.debug("getObjectInstance",
+                 "connectionId=" + connectionId
+                 +", name="+name);
+
+            return (ObjectInstance)
+                doPrivilegedOperation(
+                  GET_OBJECT_INSTANCE,
+                  params,
+                  delegationSubject);
+        } catch (PrivilegedActionException pe) {
+            Exception e = extractException(pe);
+            if (e instanceof InstanceNotFoundException)
+                throw (InstanceNotFoundException) e;
+            if (e instanceof IOException)
+                throw (IOException) e;
+            throw newIOException("Got unexpected server exception: " + e, e);
+        }
+    }
+
+    @SuppressWarnings("rawtypes")  // MarshalledObject
+    public Set<ObjectInstance>
+        queryMBeans(ObjectName name,
+                    MarshalledObject query,
+                    Subject delegationSubject)
+        throws IOException {
+        final QueryExp queryValue;
+        final boolean debug=logger.debugOn();
+
+        if (debug) logger.debug("queryMBeans",
+                 "connectionId=" + connectionId
+                 +" unwrapping query with defaultClassLoader.");
+
+        queryValue = unwrap(query, defaultContextClassLoader, QueryExp.class, delegationSubject);
+
+        try {
+            final Object params[] = new Object[] { name, queryValue };
+
+            if (debug) logger.debug("queryMBeans",
+                 "connectionId=" + connectionId
+                 +", name="+name +", query="+query);
+
+            return cast(
+                doPrivilegedOperation(
+                  QUERY_MBEANS,
+                  params,
+                  delegationSubject));
+        } catch (PrivilegedActionException pe) {
+            Exception e = extractException(pe);
+            if (e instanceof IOException)
+                throw (IOException) e;
+            throw newIOException("Got unexpected server exception: " + e, e);
+        }
+    }
+
+    @SuppressWarnings("rawtypes")  // MarshalledObject
+    public Set<ObjectName>
+        queryNames(ObjectName name,
+                   MarshalledObject query,
+                   Subject delegationSubject)
+        throws IOException {
+        final QueryExp queryValue;
+        final boolean debug=logger.debugOn();
+
+        if (debug) logger.debug("queryNames",
+                 "connectionId=" + connectionId
+                 +" unwrapping query with defaultClassLoader.");
+
+        queryValue = unwrap(query, defaultContextClassLoader, QueryExp.class, delegationSubject);
+
+        try {
+            final Object params[] = new Object[] { name, queryValue };
+
+            if (debug) logger.debug("queryNames",
+                 "connectionId=" + connectionId
+                 +", name="+name +", query="+query);
+
+            return cast(
+                doPrivilegedOperation(
+                  QUERY_NAMES,
+                  params,
+                  delegationSubject));
+        } catch (PrivilegedActionException pe) {
+            Exception e = extractException(pe);
+            if (e instanceof IOException)
+                throw (IOException) e;
+            throw newIOException("Got unexpected server exception: " + e, e);
+        }
+    }
+
+    public boolean isRegistered(ObjectName name,
+                                Subject delegationSubject) throws IOException {
+        try {
+            final Object params[] = new Object[] { name };
+            return ((Boolean)
+                doPrivilegedOperation(
+                  IS_REGISTERED,
+                  params,
+                  delegationSubject)).booleanValue();
+        } catch (PrivilegedActionException pe) {
+            Exception e = extractException(pe);
+            if (e instanceof IOException)
+                throw (IOException) e;
+            throw newIOException("Got unexpected server exception: " + e, e);
+        }
+    }
+
+    public Integer getMBeanCount(Subject delegationSubject)
+        throws IOException {
+        try {
+            final Object params[] = new Object[] { };
+
+            if (logger.debugOn()) logger.debug("getMBeanCount",
+                 "connectionId=" + connectionId);
+
+            return (Integer)
+                doPrivilegedOperation(
+                  GET_MBEAN_COUNT,
+                  params,
+                  delegationSubject);
+        } catch (PrivilegedActionException pe) {
+            Exception e = extractException(pe);
+            if (e instanceof IOException)
+                throw (IOException) e;
+            throw newIOException("Got unexpected server exception: " + e, e);
+        }
+    }
+
+    public Object getAttribute(ObjectName name,
+                               String attribute,
+                               Subject delegationSubject)
+        throws
+        MBeanException,
+        AttributeNotFoundException,
+        InstanceNotFoundException,
+        ReflectionException,
+        IOException {
+        try {
+            final Object params[] = new Object[] { name, attribute };
+            if (logger.debugOn()) logger.debug("getAttribute",
+                                   "connectionId=" + connectionId
+                                   +", name=" + name
+                                   +", attribute="+ attribute);
+
+            return
+                doPrivilegedOperation(
+                  GET_ATTRIBUTE,
+                  params,
+                  delegationSubject);
+        } catch (PrivilegedActionException pe) {
+            Exception e = extractException(pe);
+            if (e instanceof MBeanException)
+                throw (MBeanException) e;
+            if (e instanceof AttributeNotFoundException)
+                throw (AttributeNotFoundException) e;
+            if (e instanceof InstanceNotFoundException)
+                throw (InstanceNotFoundException) e;
+            if (e instanceof ReflectionException)
+                throw (ReflectionException) e;
+            if (e instanceof IOException)
+                throw (IOException) e;
+            throw newIOException("Got unexpected server exception: " + e, e);
+        }
+    }
+
+    public AttributeList getAttributes(ObjectName name,
+                                       String[] attributes,
+                                       Subject delegationSubject)
+        throws
+        InstanceNotFoundException,
+        ReflectionException,
+        IOException {
+        try {
+            final Object params[] = new Object[] { name, attributes };
+
+            if (logger.debugOn()) logger.debug("getAttributes",
+                                   "connectionId=" + connectionId
+                                   +", name=" + name
+                                   +", attributes="+ strings(attributes));
+
+            return (AttributeList)
+                doPrivilegedOperation(
+                  GET_ATTRIBUTES,
+                  params,
+                  delegationSubject);
+        } catch (PrivilegedActionException pe) {
+            Exception e = extractException(pe);
+            if (e instanceof InstanceNotFoundException)
+                throw (InstanceNotFoundException) e;
+            if (e instanceof ReflectionException)
+                throw (ReflectionException) e;
+            if (e instanceof IOException)
+                throw (IOException) e;
+            throw newIOException("Got unexpected server exception: " + e, e);
+        }
+    }
+
+    @SuppressWarnings("rawtypes")  // MarshalledObject
+    public void setAttribute(ObjectName name,
+                             MarshalledObject attribute,
+                             Subject delegationSubject)
+        throws
+        InstanceNotFoundException,
+        AttributeNotFoundException,
+        InvalidAttributeValueException,
+        MBeanException,
+        ReflectionException,
+        IOException {
+        final Attribute attr;
+        final boolean debug=logger.debugOn();
+
+        if (debug) logger.debug("setAttribute",
+                 "connectionId=" + connectionId
+                 +" unwrapping attribute with MBean extended ClassLoader.");
+
+        attr = unwrap(attribute,
+                      getClassLoaderFor(name),
+                      defaultClassLoader,
+                      Attribute.class, delegationSubject);
+
+        try {
+            final Object params[] = new Object[] { name, attr };
+
+            if (debug) logger.debug("setAttribute",
+                             "connectionId=" + connectionId
+                             +", name="+name
+                             +", attribute name="+attr.getName());
+
+            doPrivilegedOperation(
+              SET_ATTRIBUTE,
+              params,
+              delegationSubject);
+        } catch (PrivilegedActionException pe) {
+            Exception e = extractException(pe);
+            if (e instanceof InstanceNotFoundException)
+                throw (InstanceNotFoundException) e;
+            if (e instanceof AttributeNotFoundException)
+                throw (AttributeNotFoundException) e;
+            if (e instanceof InvalidAttributeValueException)
+                throw (InvalidAttributeValueException) e;
+            if (e instanceof MBeanException)
+                throw (MBeanException) e;
+            if (e instanceof ReflectionException)
+                throw (ReflectionException) e;
+            if (e instanceof IOException)
+                throw (IOException) e;
+            throw newIOException("Got unexpected server exception: " + e, e);
+        }
+    }
+
+    @SuppressWarnings("rawtypes")  // MarshalledObject
+    public AttributeList setAttributes(ObjectName name,
+                         MarshalledObject attributes,
+                         Subject delegationSubject)
+        throws
+        InstanceNotFoundException,
+        ReflectionException,
+        IOException {
+        final AttributeList attrlist;
+        final boolean debug=logger.debugOn();
+
+        if (debug) logger.debug("setAttributes",
+                 "connectionId=" + connectionId
+                 +" unwrapping attributes with MBean extended ClassLoader.");
+
+        attrlist =
+            unwrap(attributes,
+                   getClassLoaderFor(name),
+                   defaultClassLoader,
+                   AttributeList.class, delegationSubject);
+
+        try {
+            final Object params[] = new Object[] { name, attrlist };
+
+            if (debug) logger.debug("setAttributes",
+                             "connectionId=" + connectionId
+                             +", name="+name
+                             +", attribute names="+RMIConnector.getAttributesNames(attrlist));
+
+            return (AttributeList)
+                doPrivilegedOperation(
+                  SET_ATTRIBUTES,
+                  params,
+                  delegationSubject);
+        } catch (PrivilegedActionException pe) {
+            Exception e = extractException(pe);
+            if (e instanceof InstanceNotFoundException)
+                throw (InstanceNotFoundException) e;
+            if (e instanceof ReflectionException)
+                throw (ReflectionException) e;
+            if (e instanceof IOException)
+                throw (IOException) e;
+            throw newIOException("Got unexpected server exception: " + e, e);
+        }
+    }
+
+    @SuppressWarnings("rawtypes")  // MarshalledObject
+    public Object invoke(ObjectName name,
+                         String operationName,
+                         MarshalledObject params,
+                         String signature[],
+                         Subject delegationSubject)
+        throws
+        InstanceNotFoundException,
+        MBeanException,
+        ReflectionException,
+        IOException {
+
+        checkNonNull("ObjectName", name);
+        checkNonNull("Operation name", operationName);
+
+        final Object[] values;
+        final boolean debug=logger.debugOn();
+
+        if (debug) logger.debug("invoke",
+                 "connectionId=" + connectionId
+                 +" unwrapping params with MBean extended ClassLoader.");
+
+        values = nullIsEmpty(unwrap(params,
+                                    getClassLoaderFor(name),
+                                    defaultClassLoader,
+                                    Object[].class, delegationSubject));
+
+        try {
+            final Object params2[] =
+                new Object[] { name, operationName, values,
+                               nullIsEmpty(signature) };
+
+            if (debug) logger.debug("invoke",
+                             "connectionId=" + connectionId
+                             +", name="+name
+                             +", operationName="+operationName
+                             +", signature="+strings(signature));
+
+            return
+                doPrivilegedOperation(
+                  INVOKE,
+                  params2,
+                  delegationSubject);
+        } catch (PrivilegedActionException pe) {
+            Exception e = extractException(pe);
+            if (e instanceof InstanceNotFoundException)
+                throw (InstanceNotFoundException) e;
+            if (e instanceof MBeanException)
+                throw (MBeanException) e;
+            if (e instanceof ReflectionException)
+                throw (ReflectionException) e;
+            if (e instanceof IOException)
+                throw (IOException) e;
+            throw newIOException("Got unexpected server exception: " + e, e);
+        }
+    }
+
+    public String getDefaultDomain(Subject delegationSubject)
+        throws IOException {
+        try {
+            final Object params[] = new Object[] { };
+
+            if (logger.debugOn())  logger.debug("getDefaultDomain",
+                                    "connectionId=" + connectionId);
+
+            return (String)
+                doPrivilegedOperation(
+                  GET_DEFAULT_DOMAIN,
+                  params,
+                  delegationSubject);
+        } catch (PrivilegedActionException pe) {
+            Exception e = extractException(pe);
+            if (e instanceof IOException)
+                throw (IOException) e;
+            throw newIOException("Got unexpected server exception: " + e, e);
+        }
+    }
+
+    public String[] getDomains(Subject delegationSubject) throws IOException {
+        try {
+            final Object params[] = new Object[] { };
+
+            if (logger.debugOn())  logger.debug("getDomains",
+                                    "connectionId=" + connectionId);
+
+            return (String[])
+                doPrivilegedOperation(
+                  GET_DOMAINS,
+                  params,
+                  delegationSubject);
+        } catch (PrivilegedActionException pe) {
+            Exception e = extractException(pe);
+            if (e instanceof IOException)
+                throw (IOException) e;
+            throw newIOException("Got unexpected server exception: " + e, e);
+        }
+    }
+
+    public MBeanInfo getMBeanInfo(ObjectName name, Subject delegationSubject)
+        throws
+        InstanceNotFoundException,
+        IntrospectionException,
+        ReflectionException,
+        IOException {
+
+        checkNonNull("ObjectName", name);
+
+        try {
+            final Object params[] = new Object[] { name };
+
+            if (logger.debugOn())  logger.debug("getMBeanInfo",
+                                    "connectionId=" + connectionId
+                                    +", name="+name);
+
+            return (MBeanInfo)
+                doPrivilegedOperation(
+                  GET_MBEAN_INFO,
+                  params,
+                  delegationSubject);
+        } catch (PrivilegedActionException pe) {
+            Exception e = extractException(pe);
+            if (e instanceof InstanceNotFoundException)
+                throw (InstanceNotFoundException) e;
+            if (e instanceof IntrospectionException)
+                throw (IntrospectionException) e;
+            if (e instanceof ReflectionException)
+                throw (ReflectionException) e;
+            if (e instanceof IOException)
+                throw (IOException) e;
+            throw newIOException("Got unexpected server exception: " + e, e);
+        }
+    }
+
+    public boolean isInstanceOf(ObjectName name,
+                                String className,
+                                Subject delegationSubject)
+        throws InstanceNotFoundException, IOException {
+
+        checkNonNull("ObjectName", name);
+
+        try {
+            final Object params[] = new Object[] { name, className };
+
+            if (logger.debugOn())  logger.debug("isInstanceOf",
+                                    "connectionId=" + connectionId
+                                    +", name="+name
+                                    +", className="+className);
+
+            return ((Boolean)
+                doPrivilegedOperation(
+                  IS_INSTANCE_OF,
+                  params,
+                  delegationSubject)).booleanValue();
+        } catch (PrivilegedActionException pe) {
+            Exception e = extractException(pe);
+            if (e instanceof InstanceNotFoundException)
+                throw (InstanceNotFoundException) e;
+            if (e instanceof IOException)
+                throw (IOException) e;
+            throw newIOException("Got unexpected server exception: " + e, e);
+        }
+    }
+
+    @SuppressWarnings("rawtypes")  // MarshalledObject
+    public Integer[] addNotificationListeners(ObjectName[] names,
+                      MarshalledObject[] filters,
+                      Subject[] delegationSubjects)
+            throws InstanceNotFoundException, IOException {
+
+        if (names == null || filters == null) {
+            throw new IllegalArgumentException("Got null arguments.");
+        }
+
+        Subject[] sbjs = (delegationSubjects != null) ? delegationSubjects :
+        new Subject[names.length];
+        if (names.length != filters.length || filters.length != sbjs.length) {
+            final String msg =
+                "The value lengths of 3 parameters are not same.";
+            throw new IllegalArgumentException(msg);
+        }
+
+        for (int i=0; i<names.length; i++) {
+            if (names[i] == null) {
+                throw new IllegalArgumentException("Null Object name.");
+            }
+        }
+
+        int i=0;
+        ClassLoader targetCl;
+        NotificationFilter[] filterValues =
+            new NotificationFilter[names.length];
+        Integer[] ids = new Integer[names.length];
+        final boolean debug=logger.debugOn();
+
+        try {
+            for (; i<names.length; i++) {
+                targetCl = getClassLoaderFor(names[i]);
+
+                if (debug) logger.debug("addNotificationListener"+
+                                        "(ObjectName,NotificationFilter)",
+                                        "connectionId=" + connectionId +
+                      " unwrapping filter with target extended ClassLoader.");
+
+                filterValues[i] =
+                    unwrap(filters[i], targetCl, defaultClassLoader,
+                           NotificationFilter.class, sbjs[i]);
+
+                if (debug) logger.debug("addNotificationListener"+
+                                        "(ObjectName,NotificationFilter)",
+                                        "connectionId=" + connectionId
+                                        +", name=" + names[i]
+                                        +", filter=" + filterValues[i]);
+
+                ids[i] = (Integer)
+                    doPrivilegedOperation(ADD_NOTIFICATION_LISTENERS,
+                                          new Object[] { names[i],
+                                                         filterValues[i] },
+                                          sbjs[i]);
+            }
+
+            return ids;
+        } catch (Exception e) {
+            // remove all registered listeners
+            for (int j=0; j<i; j++) {
+                try {
+                    getServerNotifFwd().removeNotificationListener(names[j],
+                                                                   ids[j]);
+                } catch (Exception eee) {
+                    // strange
+                }
+            }
+
+            if (e instanceof PrivilegedActionException) {
+                e = extractException(e);
+            }
+
+            if (e instanceof ClassCastException) {
+                throw (ClassCastException) e;
+            } else if (e instanceof IOException) {
+                throw (IOException)e;
+            } else if (e instanceof InstanceNotFoundException) {
+                throw (InstanceNotFoundException) e;
+            } else if (e instanceof RuntimeException) {
+                throw (RuntimeException) e;
+            } else {
+                throw newIOException("Got unexpected server exception: "+e,e);
+            }
+        }
+    }
+
+    @SuppressWarnings("rawtypes")  // MarshalledObject
+    public void addNotificationListener(ObjectName name,
+                       ObjectName listener,
+                       MarshalledObject filter,
+                       MarshalledObject handback,
+                       Subject delegationSubject)
+        throws InstanceNotFoundException, IOException {
+
+        checkNonNull("Target MBean name", name);
+        checkNonNull("Listener MBean name", listener);
+
+        final NotificationFilter filterValue;
+        final Object handbackValue;
+        final boolean debug=logger.debugOn();
+
+        final ClassLoader targetCl = getClassLoaderFor(name);
+
+        if (debug) logger.debug("addNotificationListener"+
+                 "(ObjectName,ObjectName,NotificationFilter,Object)",
+                 "connectionId=" + connectionId
+                 +" unwrapping filter with target extended ClassLoader.");
+
+        filterValue =
+            unwrap(filter, targetCl, defaultClassLoader, NotificationFilter.class, delegationSubject);
+
+        if (debug) logger.debug("addNotificationListener"+
+                 "(ObjectName,ObjectName,NotificationFilter,Object)",
+                 "connectionId=" + connectionId
+                 +" unwrapping handback with target extended ClassLoader.");
+
+        handbackValue =
+            unwrap(handback, targetCl, defaultClassLoader, Object.class, delegationSubject);
+
+        try {
+            final Object params[] =
+                new Object[] { name, listener, filterValue, handbackValue };
+
+            if (debug) logger.debug("addNotificationListener"+
+                 "(ObjectName,ObjectName,NotificationFilter,Object)",
+                             "connectionId=" + connectionId
+                             +", name=" + name
+                             +", listenerName=" + listener
+                             +", filter=" + filterValue
+                             +", handback=" + handbackValue);
+
+            doPrivilegedOperation(
+              ADD_NOTIFICATION_LISTENER_OBJECTNAME,
+              params,
+              delegationSubject);
+        } catch (PrivilegedActionException pe) {
+            Exception e = extractException(pe);
+            if (e instanceof InstanceNotFoundException)
+                throw (InstanceNotFoundException) e;
+            if (e instanceof IOException)
+                throw (IOException) e;
+            throw newIOException("Got unexpected server exception: " + e, e);
+        }
+    }
+
+    public void removeNotificationListeners(ObjectName name,
+                                            Integer[] listenerIDs,
+                                            Subject delegationSubject)
+        throws
+        InstanceNotFoundException,
+        ListenerNotFoundException,
+        IOException {
+
+        if (name == null || listenerIDs == null)
+            throw new IllegalArgumentException("Illegal null parameter");
+
+        for (int i = 0; i < listenerIDs.length; i++) {
+            if (listenerIDs[i] == null)
+                throw new IllegalArgumentException("Null listener ID");
+        }
+
+        try {
+            final Object params[] = new Object[] { name, listenerIDs };
+
+            if (logger.debugOn()) logger.debug("removeNotificationListener"+
+                                   "(ObjectName,Integer[])",
+                                   "connectionId=" + connectionId
+                                   +", name=" + name
+                                   +", listenerIDs=" + objects(listenerIDs));
+
+            doPrivilegedOperation(
+              REMOVE_NOTIFICATION_LISTENER,
+              params,
+              delegationSubject);
+        } catch (PrivilegedActionException pe) {
+            Exception e = extractException(pe);
+            if (e instanceof InstanceNotFoundException)
+                throw (InstanceNotFoundException) e;
+            if (e instanceof ListenerNotFoundException)
+                throw (ListenerNotFoundException) e;
+            if (e instanceof IOException)
+                throw (IOException) e;
+            throw newIOException("Got unexpected server exception: " + e, e);
+        }
+    }
+
+    public void removeNotificationListener(ObjectName name,
+                                           ObjectName listener,
+                                           Subject delegationSubject)
+        throws
+        InstanceNotFoundException,
+        ListenerNotFoundException,
+        IOException {
+
+        checkNonNull("Target MBean name", name);
+        checkNonNull("Listener MBean name", listener);
+
+        try {
+            final Object params[] = new Object[] { name, listener };
+
+            if (logger.debugOn()) logger.debug("removeNotificationListener"+
+                                   "(ObjectName,ObjectName)",
+                                   "connectionId=" + connectionId
+                                   +", name=" + name
+                                   +", listenerName=" + listener);
+
+            doPrivilegedOperation(
+              REMOVE_NOTIFICATION_LISTENER_OBJECTNAME,
+              params,
+              delegationSubject);
+        } catch (PrivilegedActionException pe) {
+            Exception e = extractException(pe);
+            if (e instanceof InstanceNotFoundException)
+                throw (InstanceNotFoundException) e;
+            if (e instanceof ListenerNotFoundException)
+                throw (ListenerNotFoundException) e;
+            if (e instanceof IOException)
+                throw (IOException) e;
+            throw newIOException("Got unexpected server exception: " + e, e);
+        }
+    }
+
+    @SuppressWarnings("rawtypes")  // MarshalledObject
+    public void removeNotificationListener(ObjectName name,
+                        ObjectName listener,
+                        MarshalledObject filter,
+                        MarshalledObject handback,
+                        Subject delegationSubject)
+        throws
+        InstanceNotFoundException,
+        ListenerNotFoundException,
+        IOException {
+
+        checkNonNull("Target MBean name", name);
+        checkNonNull("Listener MBean name", listener);
+
+        final NotificationFilter filterValue;
+        final Object handbackValue;
+        final boolean debug=logger.debugOn();
+
+        final ClassLoader targetCl = getClassLoaderFor(name);
+
+        if (debug) logger.debug("removeNotificationListener"+
+                 "(ObjectName,ObjectName,NotificationFilter,Object)",
+                 "connectionId=" + connectionId
+                 +" unwrapping filter with target extended ClassLoader.");
+
+        filterValue =
+            unwrap(filter, targetCl, defaultClassLoader, NotificationFilter.class, delegationSubject);
+
+        if (debug) logger.debug("removeNotificationListener"+
+                 "(ObjectName,ObjectName,NotificationFilter,Object)",
+                 "connectionId=" + connectionId
+                 +" unwrapping handback with target extended ClassLoader.");
+
+        handbackValue =
+            unwrap(handback, targetCl, defaultClassLoader, Object.class, delegationSubject);
+
+        try {
+            final Object params[] =
+                new Object[] { name, listener, filterValue, handbackValue };
+
+            if (debug) logger.debug("removeNotificationListener"+
+                 "(ObjectName,ObjectName,NotificationFilter,Object)",
+                             "connectionId=" + connectionId
+                             +", name=" + name
+                             +", listenerName=" + listener
+                             +", filter=" + filterValue
+                             +", handback=" + handbackValue);
+
+            doPrivilegedOperation(
+              REMOVE_NOTIFICATION_LISTENER_OBJECTNAME_FILTER_HANDBACK,
+              params,
+              delegationSubject);
+        } catch (PrivilegedActionException pe) {
+            Exception e = extractException(pe);
+            if (e instanceof InstanceNotFoundException)
+                throw (InstanceNotFoundException) e;
+            if (e instanceof ListenerNotFoundException)
+                throw (ListenerNotFoundException) e;
+            if (e instanceof IOException)
+                throw (IOException) e;
+            throw newIOException("Got unexpected server exception: " + e, e);
+        }
+    }
+
+    public NotificationResult fetchNotifications(long clientSequenceNumber,
+                                                 int maxNotifications,
+                                                 long timeout)
+        throws IOException {
+
+        if (logger.debugOn()) logger.debug("fetchNotifications",
+                               "connectionId=" + connectionId
+                               +", timeout=" + timeout);
+
+        if (maxNotifications < 0 || timeout < 0)
+            throw new IllegalArgumentException("Illegal negative argument");
+
+        final boolean serverTerminated =
+            serverCommunicatorAdmin.reqIncoming();
+        try {
+            if (serverTerminated) {
+                // we must not call fetchNotifs() if the server is
+                // terminated (timeout elapsed).
+                // returns null to force the client to stop fetching
+                if (logger.debugOn()) logger.debug("fetchNotifications",
+                               "The notification server has been closed, "
+                                       + "returns null to force the client to stop fetching");
+                return null;
+            }
+            final long csn = clientSequenceNumber;
+            final int mn = maxNotifications;
+            final long t = timeout;
+            PrivilegedAction<NotificationResult> action =
+                new PrivilegedAction<NotificationResult>() {
+                    public NotificationResult run() {
+                        return getServerNotifFwd().fetchNotifs(csn, t, mn);
+                    }
+            };
+            if (acc == null)
+                return action.run();
+            else
+                return AccessController.doPrivileged(action, acc);
+        } finally {
+            serverCommunicatorAdmin.rspOutgoing();
+        }
+    }
+
+    /**
+     * <p>Returns a string representation of this object.  In general,
+     * the <code>toString</code> method returns a string that
+     * "textually represents" this object. The result should be a
+     * concise but informative representation that is easy for a
+     * person to read.</p>
+     *
+     * @return a String representation of this object.
+     **/
+    @Override
+    public String toString() {
+        return super.toString() + ": connectionId=" + connectionId;
+    }
+
+    //------------------------------------------------------------------------
+    // private classes
+    //------------------------------------------------------------------------
+
+    private class PrivilegedOperation
+            implements PrivilegedExceptionAction<Object> {
+
+        public PrivilegedOperation(int operation, Object[] params) {
+            this.operation = operation;
+            this.params = params;
+        }
+
+        public Object run() throws Exception {
+            return doOperation(operation, params);
+        }
+
+        private int operation;
+        private Object[] params;
+    }
+
+    //------------------------------------------------------------------------
+    // private classes
+    //------------------------------------------------------------------------
+    private class RMIServerCommunicatorAdmin extends ServerCommunicatorAdmin {
+        public RMIServerCommunicatorAdmin(long timeout) {
+            super(timeout);
+        }
+
+        protected void doStop() {
+            try {
+                close();
+            } catch (IOException ie) {
+                logger.warning("RMIServerCommunicatorAdmin-doStop",
+                               "Failed to close: " + ie);
+                logger.debug("RMIServerCommunicatorAdmin-doStop",ie);
+            }
+        }
+
+    }
+
+
+    //------------------------------------------------------------------------
+    // private methods
+    //------------------------------------------------------------------------
+
+    private ClassLoader getClassLoader(final ObjectName name)
+        throws InstanceNotFoundException {
+        try {
+            return
+                AccessController.doPrivileged(
+                    new PrivilegedExceptionAction<ClassLoader>() {
+                        public ClassLoader run() throws InstanceNotFoundException {
+                            return mbeanServer.getClassLoader(name);
+                        }
+                    },
+                    withPermissions(new MBeanPermission("*", "getClassLoader"))
+            );
+        } catch (PrivilegedActionException pe) {
+            throw (InstanceNotFoundException) extractException(pe);
+        }
+    }
+
+    private ClassLoader getClassLoaderFor(final ObjectName name)
+        throws InstanceNotFoundException {
+        try {
+            return (ClassLoader)
+                AccessController.doPrivileged(
+                    new PrivilegedExceptionAction<Object>() {
+                        public Object run() throws InstanceNotFoundException {
+                            return mbeanServer.getClassLoaderFor(name);
+                        }
+                    },
+                    withPermissions(new MBeanPermission("*", "getClassLoaderFor"))
+            );
+        } catch (PrivilegedActionException pe) {
+            throw (InstanceNotFoundException) extractException(pe);
+        }
+    }
+
+    private Object doPrivilegedOperation(final int operation,
+                                         final Object[] params,
+                                         final Subject delegationSubject)
+        throws PrivilegedActionException, IOException {
+
+        serverCommunicatorAdmin.reqIncoming();
+        try {
+
+            final AccessControlContext reqACC;
+            if (delegationSubject == null)
+                reqACC = acc;
+            else {
+                if (subject == null) {
+                    final String msg =
+                        "Subject delegation cannot be enabled unless " +
+                        "an authenticated subject is put in place";
+                    throw new SecurityException(msg);
+                }
+                reqACC = subjectDelegator.delegatedContext(
+                    acc, delegationSubject, removeCallerContext);
+            }
+
+            PrivilegedOperation op =
+                new PrivilegedOperation(operation, params);
+            if (reqACC == null) {
+                try {
+                    return op.run();
+                } catch (Exception e) {
+                    if (e instanceof RuntimeException)
+                        throw (RuntimeException) e;
+                    throw new PrivilegedActionException(e);
+                }
+            } else {
+                return AccessController.doPrivileged(op, reqACC);
+            }
+        } catch (Error e) {
+            throw new JMXServerErrorException(e.toString(),e);
+        } finally {
+            serverCommunicatorAdmin.rspOutgoing();
+        }
+    }
+
+    private Object doOperation(int operation, Object[] params)
+        throws Exception {
+
+        switch (operation) {
+
+        case CREATE_MBEAN:
+            return mbeanServer.createMBean((String)params[0],
+                                           (ObjectName)params[1]);
+
+        case CREATE_MBEAN_LOADER:
+            return mbeanServer.createMBean((String)params[0],
+                                           (ObjectName)params[1],
+                                           (ObjectName)params[2]);
+
+        case CREATE_MBEAN_PARAMS:
+            return mbeanServer.createMBean((String)params[0],
+                                           (ObjectName)params[1],
+                                           (Object[])params[2],
+                                           (String[])params[3]);
+
+        case CREATE_MBEAN_LOADER_PARAMS:
+            return mbeanServer.createMBean((String)params[0],
+                                           (ObjectName)params[1],
+                                           (ObjectName)params[2],
+                                           (Object[])params[3],
+                                           (String[])params[4]);
+
+        case GET_ATTRIBUTE:
+            return mbeanServer.getAttribute((ObjectName)params[0],
+                                            (String)params[1]);
+
+        case GET_ATTRIBUTES:
+            return mbeanServer.getAttributes((ObjectName)params[0],
+                                             (String[])params[1]);
+
+        case GET_DEFAULT_DOMAIN:
+            return mbeanServer.getDefaultDomain();
+
+        case GET_DOMAINS:
+            return mbeanServer.getDomains();
+
+        case GET_MBEAN_COUNT:
+            return mbeanServer.getMBeanCount();
+
+        case GET_MBEAN_INFO:
+            return mbeanServer.getMBeanInfo((ObjectName)params[0]);
+
+        case GET_OBJECT_INSTANCE:
+            return mbeanServer.getObjectInstance((ObjectName)params[0]);
+
+        case INVOKE:
+            return mbeanServer.invoke((ObjectName)params[0],
+                                      (String)params[1],
+                                      (Object[])params[2],
+                                      (String[])params[3]);
+
+        case IS_INSTANCE_OF:
+            return mbeanServer.isInstanceOf((ObjectName)params[0],
+                                            (String)params[1])
+                ? Boolean.TRUE : Boolean.FALSE;
+
+        case IS_REGISTERED:
+            return mbeanServer.isRegistered((ObjectName)params[0])
+                ? Boolean.TRUE : Boolean.FALSE;
+
+        case QUERY_MBEANS:
+            return mbeanServer.queryMBeans((ObjectName)params[0],
+                                           (QueryExp)params[1]);
+
+        case QUERY_NAMES:
+            return mbeanServer.queryNames((ObjectName)params[0],
+                                          (QueryExp)params[1]);
+
+        case SET_ATTRIBUTE:
+            mbeanServer.setAttribute((ObjectName)params[0],
+                                     (Attribute)params[1]);
+            return null;
+
+        case SET_ATTRIBUTES:
+            return mbeanServer.setAttributes((ObjectName)params[0],
+                                             (AttributeList)params[1]);
+
+        case UNREGISTER_MBEAN:
+            mbeanServer.unregisterMBean((ObjectName)params[0]);
+            return null;
+
+        case ADD_NOTIFICATION_LISTENERS:
+            return getServerNotifFwd().addNotificationListener(
+                                                (ObjectName)params[0],
+                                                (NotificationFilter)params[1]);
+
+        case ADD_NOTIFICATION_LISTENER_OBJECTNAME:
+            mbeanServer.addNotificationListener((ObjectName)params[0],
+                                                (ObjectName)params[1],
+                                                (NotificationFilter)params[2],
+                                                params[3]);
+            return null;
+
+        case REMOVE_NOTIFICATION_LISTENER:
+            getServerNotifFwd().removeNotificationListener(
+                                                   (ObjectName)params[0],
+                                                   (Integer[])params[1]);
+            return null;
+
+        case REMOVE_NOTIFICATION_LISTENER_OBJECTNAME:
+            mbeanServer.removeNotificationListener((ObjectName)params[0],
+                                                   (ObjectName)params[1]);
+            return null;
+
+        case REMOVE_NOTIFICATION_LISTENER_OBJECTNAME_FILTER_HANDBACK:
+            mbeanServer.removeNotificationListener(
+                                          (ObjectName)params[0],
+                                          (ObjectName)params[1],
+                                          (NotificationFilter)params[2],
+                                          params[3]);
+            return null;
+
+        default:
+            throw new IllegalArgumentException("Invalid operation");
+        }
+    }
+
+    private static class SetCcl implements PrivilegedExceptionAction<ClassLoader> {
+        private final ClassLoader classLoader;
+
+        SetCcl(ClassLoader classLoader) {
+            this.classLoader = classLoader;
+        }
+
+        public ClassLoader run() {
+            Thread currentThread = Thread.currentThread();
+            ClassLoader old = currentThread.getContextClassLoader();
+            currentThread.setContextClassLoader(classLoader);
+            return old;
+        }
+    }
+
+    private <T> T unwrap(final MarshalledObject<?> mo,
+                                final ClassLoader cl,
+                                final Class<T> wrappedClass,
+                                Subject delegationSubject)
+            throws IOException {
+        if (mo == null) {
+            return null;
+        }
+        try {
+            final ClassLoader old = AccessController.doPrivileged(new SetCcl(cl));
+            try{
+                final AccessControlContext reqACC;
+                if (delegationSubject == null)
+                    reqACC = acc;
+                else {
+                    if (subject == null) {
+                        final String msg =
+                            "Subject delegation cannot be enabled unless " +
+                            "an authenticated subject is put in place";
+                        throw new SecurityException(msg);
+                    }
+                    reqACC = subjectDelegator.delegatedContext(
+                        acc, delegationSubject, removeCallerContext);
+                }
+                if(reqACC != null){
+                    return AccessController.doPrivileged(
+                            (PrivilegedExceptionAction<T>) () ->
+                                    wrappedClass.cast(mo.get()), reqACC);
+                }else{
+                    return wrappedClass.cast(mo.get());
+                }
+            }finally{
+                AccessController.doPrivileged(new SetCcl(old));
+            }
+        } catch (PrivilegedActionException pe) {
+            Exception e = extractException(pe);
+            if (e instanceof IOException) {
+                throw (IOException) e;
+            }
+            if (e instanceof ClassNotFoundException) {
+                throw new UnmarshalException(e.toString(), e);
+            }
+            logger.warning("unwrap", "Failed to unmarshall object: " + e);
+            logger.debug("unwrap", e);
+        }catch (ClassNotFoundException ex) {
+            logger.warning("unwrap", "Failed to unmarshall object: " + ex);
+            logger.debug("unwrap", ex);
+            throw new UnmarshalException(ex.toString(), ex);
+        }
+        return null;
+    }
+
+    private <T> T unwrap(final MarshalledObject<?> mo,
+                                final ClassLoader cl1,
+                                final ClassLoader cl2,
+                                final Class<T> wrappedClass,
+                                Subject delegationSubject)
+        throws IOException {
+        if (mo == null) {
+            return null;
+        }
+        try {
+            ClassLoader orderCL = AccessController.doPrivileged(
+                new PrivilegedExceptionAction<ClassLoader>() {
+                    public ClassLoader run() throws Exception {
+                        return new CombinedClassLoader(Thread.currentThread().getContextClassLoader(),
+                                new OrderClassLoaders(cl1, cl2));
+                    }
+                }
+            );
+            return unwrap(mo, orderCL, wrappedClass,delegationSubject);
+        } catch (PrivilegedActionException pe) {
+            Exception e = extractException(pe);
+            if (e instanceof IOException) {
+                throw (IOException) e;
+            }
+            if (e instanceof ClassNotFoundException) {
+                throw new UnmarshalException(e.toString(), e);
+            }
+            logger.warning("unwrap", "Failed to unmarshall object: " + e);
+            logger.debug("unwrap", e);
+        }
+        return null;
+    }
+
+    /**
+     * Construct a new IOException with a nested exception.
+     * The nested exception is set only if JDK {@literal >= 1.4}
+     */
+    private static IOException newIOException(String message,
+                                              Throwable cause) {
+        final IOException x = new IOException(message);
+        return EnvHelp.initCause(x,cause);
+    }
+
+    /**
+     * Iterate until we extract the real exception
+     * from a stack of PrivilegedActionExceptions.
+     */
+    private static Exception extractException(Exception e) {
+        while (e instanceof PrivilegedActionException) {
+            e = ((PrivilegedActionException)e).getException();
+        }
+        return e;
+    }
+
+    private static final Object[] NO_OBJECTS = new Object[0];
+    private static final String[] NO_STRINGS = new String[0];
+
+    /*
+     * The JMX spec doesn't explicitly say that a null Object[] or
+     * String[] in e.g. MBeanServer.invoke is equivalent to an empty
+     * array, but the RI behaves that way.  In the interests of
+     * maximal interoperability, we make it so even when we're
+     * connected to some other JMX implementation that might not do
+     * that.  This should be clarified in the next version of JMX.
+     */
+    private static Object[] nullIsEmpty(Object[] array) {
+        return (array == null) ? NO_OBJECTS : array;
+    }
+
+    private static String[] nullIsEmpty(String[] array) {
+        return (array == null) ? NO_STRINGS : array;
+    }
+
+    /*
+     * Similarly, the JMX spec says for some but not all methods in
+     * MBeanServer that take an ObjectName target, that if it's null
+     * you get this exception.  We specify it for all of them, and
+     * make it so for the ones where it's not specified in JMX even if
+     * the JMX implementation doesn't do so.
+     */
+    private static void checkNonNull(String what, Object x) {
+        if (x == null) {
+            RuntimeException wrapped =
+                new IllegalArgumentException(what + " must not be null");
+            throw new RuntimeOperationsException(wrapped);
+        }
+    }
+
+    //------------------------------------------------------------------------
+    // private variables
+    //------------------------------------------------------------------------
+
+    private final Subject subject;
+
+    private final SubjectDelegator subjectDelegator;
+
+    private final boolean removeCallerContext;
+
+    private final AccessControlContext acc;
+
+    private final RMIServerImpl rmiServer;
+
+    private final MBeanServer mbeanServer;
+
+    private final ClassLoader defaultClassLoader;
+
+    private final ClassLoader defaultContextClassLoader;
+
+    private final ClassLoaderWithRepository classLoaderWithRepository;
+
+    private boolean terminated = false;
+
+    private final String connectionId;
+
+    private final ServerCommunicatorAdmin serverCommunicatorAdmin;
+
+    // Method IDs for doOperation
+    //---------------------------
+
+    private final static int
+        ADD_NOTIFICATION_LISTENERS                              = 1;
+    private final static int
+        ADD_NOTIFICATION_LISTENER_OBJECTNAME                    = 2;
+    private final static int
+        CREATE_MBEAN                                            = 3;
+    private final static int
+        CREATE_MBEAN_PARAMS                                     = 4;
+    private final static int
+        CREATE_MBEAN_LOADER                                     = 5;
+    private final static int
+        CREATE_MBEAN_LOADER_PARAMS                              = 6;
+    private final static int
+        GET_ATTRIBUTE                                           = 7;
+    private final static int
+        GET_ATTRIBUTES                                          = 8;
+    private final static int
+        GET_DEFAULT_DOMAIN                                      = 9;
+    private final static int
+        GET_DOMAINS                                             = 10;
+    private final static int
+        GET_MBEAN_COUNT                                         = 11;
+    private final static int
+        GET_MBEAN_INFO                                          = 12;
+    private final static int
+        GET_OBJECT_INSTANCE                                     = 13;
+    private final static int
+        INVOKE                                                  = 14;
+    private final static int
+        IS_INSTANCE_OF                                          = 15;
+    private final static int
+        IS_REGISTERED                                           = 16;
+    private final static int
+        QUERY_MBEANS                                            = 17;
+    private final static int
+        QUERY_NAMES                                             = 18;
+    private final static int
+        REMOVE_NOTIFICATION_LISTENER                            = 19;
+    private final static int
+        REMOVE_NOTIFICATION_LISTENER_OBJECTNAME                 = 20;
+    private final static int
+        REMOVE_NOTIFICATION_LISTENER_OBJECTNAME_FILTER_HANDBACK = 21;
+    private final static int
+        SET_ATTRIBUTE                                           = 22;
+    private final static int
+        SET_ATTRIBUTES                                          = 23;
+    private final static int
+        UNREGISTER_MBEAN                                        = 24;
+
+    // SERVER NOTIFICATION
+    //--------------------
+
+    private ServerNotifForwarder serverNotifForwarder;
+    private Map<String, ?> env;
+
+    // TRACES & DEBUG
+    //---------------
+
+    private static String objects(final Object[] objs) {
+        if (objs == null)
+            return "null";
+        else
+            return Arrays.asList(objs).toString();
+    }
+
+    private static String strings(final String[] strs) {
+        return objects(strs);
+    }
+
+    private static final ClassLogger logger =
+        new ClassLogger("javax.management.remote.rmi", "RMIConnectionImpl");
+
+    private static final class CombinedClassLoader extends ClassLoader {
+
+        private final static class ClassLoaderWrapper extends ClassLoader {
+            ClassLoaderWrapper(ClassLoader cl) {
+                super(cl);
+            }
+
+            @Override
+            protected Class<?> loadClass(String name, boolean resolve)
+                    throws ClassNotFoundException {
+                return super.loadClass(name, resolve);
+            }
+        };
+
+        final ClassLoaderWrapper defaultCL;
+
+        private CombinedClassLoader(ClassLoader parent, ClassLoader defaultCL) {
+            super(parent);
+            this.defaultCL = new ClassLoaderWrapper(defaultCL);
+        }
+
+        @Override
+        protected Class<?> loadClass(String name, boolean resolve)
+        throws ClassNotFoundException {
+            ReflectUtil.checkPackageAccess(name);
+            try {
+                super.loadClass(name, resolve);
+            } catch(Exception e) {
+                for(Throwable t = e; t != null; t = t.getCause()) {
+                    if(t instanceof SecurityException) {
+                        throw t==e?(SecurityException)t:new SecurityException(t.getMessage(), e);
+                    }
+                }
+            }
+            final Class<?> cl = defaultCL.loadClass(name, resolve);
+            return cl;
+        }
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.management.rmi/share/classes/javax/management/remote/rmi/RMIConnector.java	Thu Feb 02 16:50:46 2017 +0000
@@ -0,0 +1,2309 @@
+/*
+ * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package javax.management.remote.rmi;
+
+import com.sun.jmx.remote.internal.ClientCommunicatorAdmin;
+import com.sun.jmx.remote.internal.ClientListenerInfo;
+import com.sun.jmx.remote.internal.ClientNotifForwarder;
+import com.sun.jmx.remote.internal.rmi.ProxyRef;
+import com.sun.jmx.remote.util.ClassLogger;
+import com.sun.jmx.remote.util.EnvHelp;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InvalidObjectException;
+import java.io.ObjectInputStream;
+import java.io.ObjectStreamClass;
+import java.io.Serializable;
+import java.lang.ref.WeakReference;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Module;
+import java.lang.reflect.Proxy;
+import java.net.MalformedURLException;
+import java.rmi.MarshalledObject;
+import java.rmi.NoSuchObjectException;
+import java.rmi.Remote;
+import java.rmi.ServerException;
+import java.rmi.UnmarshalException;
+import java.rmi.server.RMIClientSocketFactory;
+import java.rmi.server.RemoteObject;
+import java.rmi.server.RemoteObjectInvocationHandler;
+import java.rmi.server.RemoteRef;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedExceptionAction;
+import java.security.ProtectionDomain;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.WeakHashMap;
+import java.util.stream.Collectors;
+import javax.management.Attribute;
+import javax.management.AttributeList;
+import javax.management.AttributeNotFoundException;
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.InstanceNotFoundException;
+import javax.management.IntrospectionException;
+import javax.management.InvalidAttributeValueException;
+import javax.management.ListenerNotFoundException;
+import javax.management.MBeanException;
+import javax.management.MBeanInfo;
+import javax.management.MBeanRegistrationException;
+import javax.management.MBeanServerConnection;
+import javax.management.MBeanServerDelegate;
+import javax.management.MBeanServerNotification;
+import javax.management.NotCompliantMBeanException;
+import javax.management.Notification;
+import javax.management.NotificationBroadcasterSupport;
+import javax.management.NotificationFilter;
+import javax.management.NotificationFilterSupport;
+import javax.management.NotificationListener;
+import javax.management.ObjectInstance;
+import javax.management.ObjectName;
+import javax.management.QueryExp;
+import javax.management.ReflectionException;
+import javax.management.remote.JMXConnectionNotification;
+import javax.management.remote.JMXConnector;
+import javax.management.remote.JMXConnectorFactory;
+import javax.management.remote.JMXServiceURL;
+import javax.management.remote.NotificationResult;
+import javax.management.remote.JMXAddressable;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+import javax.rmi.ssl.SslRMIClientSocketFactory;
+import javax.security.auth.Subject;
+import jdk.internal.module.Modules;
+import sun.reflect.misc.ReflectUtil;
+import sun.rmi.server.UnicastRef2;
+import sun.rmi.transport.LiveRef;
+import java.io.NotSerializableException;
+
+/**
+ * <p>A connection to a remote RMI connector.  Usually, such
+ * connections are made using {@link
+ * javax.management.remote.JMXConnectorFactory JMXConnectorFactory}.
+ * However, specialized applications can use this class directly, for
+ * example with an {@link RMIServer} stub obtained without going
+ * through JNDI.</p>
+ *
+ * @since 1.5
+ */
+public class RMIConnector implements JMXConnector, Serializable, JMXAddressable {
+
+    private static final ClassLogger logger =
+            new ClassLogger("javax.management.remote.rmi", "RMIConnector");
+
+    private static final long serialVersionUID = 817323035842634473L;
+
+    static final class Util {
+        private Util() {}
+
+        /* This method can be used by code that is deliberately violating the
+         * allowed checked casts.  Rather than marking the whole method containing
+         * the code with @SuppressWarnings, you can use a call to this method for
+         * the exact place where you need to escape the constraints.  Typically
+         * you will "import static" this method and then write either
+         *    X x = cast(y);
+         * or, if that doesn't work (e.g. X is a type variable)
+         *    Util.<X>cast(y);
+         */
+        @SuppressWarnings("unchecked")
+        public static <T> T cast(Object x) {
+            return (T) x;
+        }
+    }
+
+    private RMIConnector(RMIServer rmiServer, JMXServiceURL address,
+            Map<String, ?> environment) {
+        if (rmiServer == null && address == null) throw new
+                IllegalArgumentException("rmiServer and jmxServiceURL both null");
+        initTransients();
+
+        this.rmiServer = rmiServer;
+        this.jmxServiceURL = address;
+        if (environment == null) {
+            this.env = Collections.emptyMap();
+        } else {
+            EnvHelp.checkAttributes(environment);
+            this.env = Collections.unmodifiableMap(environment);
+        }
+    }
+
+    /**
+     * <p>Constructs an {@code RMIConnector} that will connect
+     * the RMI connector server with the given address.</p>
+     *
+     * <p>The address can refer directly to the connector server,
+     * using the following syntax:</p>
+     *
+     * <pre>
+     * service:jmx:rmi://<em>[host[:port]]</em>/stub/<em>encoded-stub</em>
+     * </pre>
+     *
+     * <p>(Here, the square brackets {@code []} are not part of the
+     * address but indicate that the host and port are optional.)</p>
+     *
+     * <p>The address can instead indicate where to find an RMI stub
+     * through JNDI, using the following syntax:</p>
+     *
+     * <pre>
+     * service:jmx:rmi://<em>[host[:port]]</em>/jndi/<em>jndi-name</em>
+     * </pre>
+     *
+     * <p>An implementation may also recognize additional address
+     * syntaxes, for example:</p>
+     *
+     * <pre>
+     * service:jmx:iiop://<em>[host[:port]]</em>/stub/<em>encoded-stub</em>
+     * </pre>
+     *
+     * @param url the address of the RMI connector server.
+     *
+     * @param environment additional attributes specifying how to make
+     * the connection.  For JNDI-based addresses, these attributes can
+     * usefully include JNDI attributes recognized by {@link
+     * InitialContext#InitialContext(Hashtable) InitialContext}.  This
+     * parameter can be null, which is equivalent to an empty Map.
+     *
+     * @exception IllegalArgumentException if {@code url}
+     * is null.
+     */
+    public RMIConnector(JMXServiceURL url, Map<String,?> environment) {
+        this(null, url, environment);
+    }
+
+    /**
+     * <p>Constructs an {@code RMIConnector} using the given RMI stub.
+     *
+     * @param rmiServer an RMI stub representing the RMI connector server.
+     * @param environment additional attributes specifying how to make
+     * the connection.  This parameter can be null, which is
+     * equivalent to an empty Map.
+     *
+     * @exception IllegalArgumentException if {@code rmiServer}
+     * is null.
+     */
+    public RMIConnector(RMIServer rmiServer, Map<String,?> environment) {
+        this(rmiServer, null, environment);
+    }
+
+    /**
+     * <p>Returns a string representation of this object.  In general,
+     * the {@code toString} method returns a string that
+     * "textually represents" this object. The result should be a
+     * concise but informative representation that is easy for a
+     * person to read.</p>
+     *
+     * @return a String representation of this object.
+     **/
+    @Override
+    public String toString() {
+        final StringBuilder b = new StringBuilder(this.getClass().getName());
+        b.append(":");
+        if (rmiServer != null) {
+            b.append(" rmiServer=").append(rmiServer.toString());
+        }
+        if (jmxServiceURL != null) {
+            if (rmiServer!=null) b.append(",");
+            b.append(" jmxServiceURL=").append(jmxServiceURL.toString());
+        }
+        return b.toString();
+    }
+
+    /**
+     * <p>The address of this connector.</p>
+     *
+     * @return the address of this connector, or null if it
+     * does not have one.
+     *
+     * @since 1.6
+     */
+    public JMXServiceURL getAddress() {
+        return jmxServiceURL;
+    }
+
+    //--------------------------------------------------------------------
+    // implements JMXConnector interface
+    //--------------------------------------------------------------------
+
+    /**
+     * @throws IOException if the connection could not be made because of a
+     *   communication problem
+     */
+    public void connect() throws IOException {
+        connect(null);
+    }
+
+    /**
+     * @throws IOException if the connection could not be made because of a
+     *   communication problem
+     */
+    public synchronized void connect(Map<String,?> environment)
+    throws IOException {
+        final boolean tracing = logger.traceOn();
+        String        idstr   = (tracing?"["+this.toString()+"]":null);
+
+        if (terminated) {
+            logger.trace("connect",idstr + " already closed.");
+            throw new IOException("Connector closed");
+        }
+        if (connected) {
+            logger.trace("connect",idstr + " already connected.");
+            return;
+        }
+
+        try {
+            if (tracing) logger.trace("connect",idstr + " connecting...");
+
+            final Map<String, Object> usemap =
+                    new HashMap<String, Object>((this.env==null) ?
+                        Collections.<String, Object>emptyMap() : this.env);
+
+
+            if (environment != null) {
+                EnvHelp.checkAttributes(environment);
+                usemap.putAll(environment);
+            }
+
+            // Get RMIServer stub from directory or URL encoding if needed.
+            if (tracing) logger.trace("connect",idstr + " finding stub...");
+            RMIServer stub = (rmiServer!=null)?rmiServer:
+                findRMIServer(jmxServiceURL, usemap);
+
+            // Check for secure RMIServer stub if the corresponding
+            // client-side environment property is set to "true".
+            //
+            String stringBoolean =  (String) usemap.get("jmx.remote.x.check.stub");
+            boolean checkStub = EnvHelp.computeBooleanFromString(stringBoolean);
+
+            if (checkStub) checkStub(stub, rmiServerImplStubClass);
+
+            if (tracing) logger.trace("connect",idstr + " connecting stub...");
+            idstr = (tracing?"["+this.toString()+"]":null);
+
+            // Calling newClient on the RMIServer stub.
+            if (tracing)
+                logger.trace("connect",idstr + " getting connection...");
+            Object credentials = usemap.get(CREDENTIALS);
+
+            try {
+                connection = getConnection(stub, credentials, checkStub);
+            } catch (java.rmi.RemoteException re) {
+                throw re;
+            }
+
+            // Always use one of:
+            //   ClassLoader provided in Map at connect time,
+            //   or contextClassLoader at connect time.
+            if (tracing)
+                logger.trace("connect",idstr + " getting class loader...");
+            defaultClassLoader = EnvHelp.resolveClientClassLoader(usemap);
+
+            usemap.put(JMXConnectorFactory.DEFAULT_CLASS_LOADER,
+                    defaultClassLoader);
+
+            rmiNotifClient = new RMINotifClient(defaultClassLoader, usemap);
+
+            env = usemap;
+            final long checkPeriod = EnvHelp.getConnectionCheckPeriod(usemap);
+            communicatorAdmin = new RMIClientCommunicatorAdmin(checkPeriod);
+
+            connected = true;
+
+            // The connectionId variable is used in doStart(), when
+            // reconnecting, to identify the "old" connection.
+            //
+            connectionId = getConnectionId();
+
+            Notification connectedNotif =
+                    new JMXConnectionNotification(JMXConnectionNotification.OPENED,
+                    this,
+                    connectionId,
+                    clientNotifSeqNo++,
+                    "Successful connection",
+                    null);
+            sendNotification(connectedNotif);
+
+            if (tracing) logger.trace("connect",idstr + " done...");
+        } catch (IOException e) {
+            if (tracing)
+                logger.trace("connect",idstr + " failed to connect: " + e);
+            throw e;
+        } catch (RuntimeException e) {
+            if (tracing)
+                logger.trace("connect",idstr + " failed to connect: " + e);
+            throw e;
+        } catch (NamingException e) {
+            final String msg = "Failed to retrieve RMIServer stub: " + e;
+            if (tracing) logger.trace("connect",idstr + " " + msg);
+            throw EnvHelp.initCause(new IOException(msg),e);
+        }
+    }
+
+    public synchronized String getConnectionId() throws IOException {
+        if (terminated || !connected) {
+            if (logger.traceOn())
+                logger.trace("getConnectionId","["+this.toString()+
+                        "] not connected.");
+
+            throw new IOException("Not connected");
+        }
+
+        // we do a remote call to have an IOException if the connection is broken.
+        // see the bug 4939578
+        return connection.getConnectionId();
+    }
+
+    public synchronized MBeanServerConnection getMBeanServerConnection()
+    throws IOException {
+        return getMBeanServerConnection(null);
+    }
+
+    public synchronized MBeanServerConnection
+            getMBeanServerConnection(Subject delegationSubject)
+            throws IOException {
+
+        if (terminated) {
+            if (logger.traceOn())
+                logger.trace("getMBeanServerConnection","[" + this.toString() +
+                        "] already closed.");
+            throw new IOException("Connection closed");
+        } else if (!connected) {
+            if (logger.traceOn())
+                logger.trace("getMBeanServerConnection","[" + this.toString() +
+                        "] is not connected.");
+            throw new IOException("Not connected");
+        }
+
+        return getConnectionWithSubject(delegationSubject);
+    }
+
+    public void
+            addConnectionNotificationListener(NotificationListener listener,
+            NotificationFilter filter,
+            Object handback) {
+        if (listener == null)
+            throw new NullPointerException("listener");
+        connectionBroadcaster.addNotificationListener(listener, filter,
+                handback);
+    }
+
+    public void
+            removeConnectionNotificationListener(NotificationListener listener)
+            throws ListenerNotFoundException {
+        if (listener == null)
+            throw new NullPointerException("listener");
+        connectionBroadcaster.removeNotificationListener(listener);
+    }
+
+    public void
+            removeConnectionNotificationListener(NotificationListener listener,
+            NotificationFilter filter,
+            Object handback)
+            throws ListenerNotFoundException {
+        if (listener == null)
+            throw new NullPointerException("listener");
+        connectionBroadcaster.removeNotificationListener(listener, filter,
+                handback);
+    }
+
+    private void sendNotification(Notification n) {
+        connectionBroadcaster.sendNotification(n);
+    }
+
+    public synchronized void close() throws IOException {
+        close(false);
+    }
+
+    // allows to do close after setting the flag "terminated" to true.
+    // It is necessary to avoid a deadlock, see 6296324
+    private synchronized void close(boolean intern) throws IOException {
+        final boolean tracing = logger.traceOn();
+        final boolean debug   = logger.debugOn();
+        final String  idstr   = (tracing?"["+this.toString()+"]":null);
+
+        if (!intern) {
+            // Return if already cleanly closed.
+            //
+            if (terminated) {
+                if (closeException == null) {
+                    if (tracing) logger.trace("close",idstr + " already closed.");
+                    return;
+                }
+            } else {
+                terminated = true;
+            }
+        }
+
+        if (closeException != null && tracing) {
+            // Already closed, but not cleanly. Attempt again.
+            //
+            if (tracing) {
+                logger.trace("close",idstr + " had failed: " + closeException);
+                logger.trace("close",idstr + " attempting to close again.");
+            }
+        }
+
+        String savedConnectionId = null;
+        if (connected) {
+            savedConnectionId = connectionId;
+        }
+
+        closeException = null;
+
+        if (tracing) logger.trace("close",idstr + " closing.");
+
+        if (communicatorAdmin != null) {
+            communicatorAdmin.terminate();
+        }
+
+        if (rmiNotifClient != null) {
+            try {
+                rmiNotifClient.terminate();
+                if (tracing) logger.trace("close",idstr +
+                        " RMI Notification client terminated.");
+            } catch (RuntimeException x) {
+                closeException = x;
+                if (tracing) logger.trace("close",idstr +
+                        " Failed to terminate RMI Notification client: " + x);
+                if (debug) logger.debug("close",x);
+            }
+        }
+
+        if (connection != null) {
+            try {
+                connection.close();
+                if (tracing) logger.trace("close",idstr + " closed.");
+            } catch (NoSuchObjectException nse) {
+                // OK, the server maybe closed itself.
+            } catch (IOException e) {
+                closeException = e;
+                if (tracing) logger.trace("close",idstr +
+                        " Failed to close RMIServer: " + e);
+                if (debug) logger.debug("close",e);
+            }
+        }
+
+        // Clean up MBeanServerConnection table
+        //
+        rmbscMap.clear();
+
+        /* Send notification of closure.  We don't do this if the user
+         * never called connect() on the connector, because there's no
+         * connection id in that case.  */
+
+        if (savedConnectionId != null) {
+            Notification closedNotif =
+                    new JMXConnectionNotification(JMXConnectionNotification.CLOSED,
+                    this,
+                    savedConnectionId,
+                    clientNotifSeqNo++,
+                    "Client has been closed",
+                    null);
+            sendNotification(closedNotif);
+        }
+
+        // throw exception if needed
+        //
+        if (closeException != null) {
+            if (tracing) logger.trace("close",idstr + " failed to close: " +
+                    closeException);
+            if (closeException instanceof IOException)
+                throw (IOException) closeException;
+            if (closeException instanceof RuntimeException)
+                throw (RuntimeException) closeException;
+            final IOException x =
+                    new IOException("Failed to close: " + closeException);
+            throw EnvHelp.initCause(x,closeException);
+        }
+    }
+
+    // added for re-connection
+    private Integer addListenerWithSubject(ObjectName name,
+                                           MarshalledObject<NotificationFilter> filter,
+                                           Subject delegationSubject,
+                                           boolean reconnect)
+        throws InstanceNotFoundException, IOException {
+
+        final boolean debug = logger.debugOn();
+        if (debug)
+            logger.debug("addListenerWithSubject",
+                    "(ObjectName,MarshalledObject,Subject)");
+
+        final ObjectName[] names = new ObjectName[] {name};
+        final MarshalledObject<NotificationFilter>[] filters =
+                Util.cast(new MarshalledObject<?>[] {filter});
+        final Subject[] delegationSubjects = new Subject[] {
+            delegationSubject
+        };
+
+        final Integer[] listenerIDs =
+                addListenersWithSubjects(names,filters,delegationSubjects,
+                reconnect);
+
+        if (debug) logger.debug("addListenerWithSubject","listenerID="
+                + listenerIDs[0]);
+        return listenerIDs[0];
+    }
+
+    // added for re-connection
+    private Integer[] addListenersWithSubjects(ObjectName[]       names,
+                             MarshalledObject<NotificationFilter>[] filters,
+                             Subject[]          delegationSubjects,
+                             boolean            reconnect)
+        throws InstanceNotFoundException, IOException {
+
+        final boolean debug = logger.debugOn();
+        if (debug)
+            logger.debug("addListenersWithSubjects",
+                    "(ObjectName[],MarshalledObject[],Subject[])");
+
+        final ClassLoader old = pushDefaultClassLoader();
+        Integer[] listenerIDs = null;
+
+        try {
+            listenerIDs = connection.addNotificationListeners(names,
+                    filters,
+                    delegationSubjects);
+        } catch (NoSuchObjectException noe) {
+            // maybe reconnect
+            if (reconnect) {
+                communicatorAdmin.gotIOException(noe);
+
+                listenerIDs = connection.addNotificationListeners(names,
+                        filters,
+                        delegationSubjects);
+            } else {
+                throw noe;
+            }
+        } catch (IOException ioe) {
+            // send a failed notif if necessary
+            communicatorAdmin.gotIOException(ioe);
+        } finally {
+            popDefaultClassLoader(old);
+        }
+
+        if (debug) logger.debug("addListenersWithSubjects","registered "
+                + ((listenerIDs==null)?0:listenerIDs.length)
+                + " listener(s)");
+        return listenerIDs;
+    }
+
+    //--------------------------------------------------------------------
+    // Implementation of MBeanServerConnection
+    //--------------------------------------------------------------------
+    private class RemoteMBeanServerConnection implements MBeanServerConnection {
+        private Subject delegationSubject;
+
+        public RemoteMBeanServerConnection() {
+            this(null);
+        }
+
+        public RemoteMBeanServerConnection(Subject delegationSubject) {
+            this.delegationSubject = delegationSubject;
+        }
+
+        public ObjectInstance createMBean(String className,
+                ObjectName name)
+                throws ReflectionException,
+                InstanceAlreadyExistsException,
+                MBeanRegistrationException,
+                MBeanException,
+                NotCompliantMBeanException,
+                IOException {
+            if (logger.debugOn())
+                logger.debug("createMBean(String,ObjectName)",
+                        "className=" + className + ", name=" +
+                        name);
+
+            final ClassLoader old = pushDefaultClassLoader();
+            try {
+                return connection.createMBean(className,
+                        name,
+                        delegationSubject);
+            } catch (IOException ioe) {
+                communicatorAdmin.gotIOException(ioe);
+
+                return connection.createMBean(className,
+                        name,
+                        delegationSubject);
+            } finally {
+                popDefaultClassLoader(old);
+            }
+        }
+
+        public ObjectInstance createMBean(String className,
+                ObjectName name,
+                ObjectName loaderName)
+                throws ReflectionException,
+                InstanceAlreadyExistsException,
+                MBeanRegistrationException,
+                MBeanException,
+                NotCompliantMBeanException,
+                InstanceNotFoundException,
+                IOException {
+
+            if (logger.debugOn())
+                logger.debug("createMBean(String,ObjectName,ObjectName)",
+                        "className=" + className + ", name="
+                        + name + ", loaderName="
+                        + loaderName + ")");
+
+            final ClassLoader old = pushDefaultClassLoader();
+            try {
+                return connection.createMBean(className,
+                        name,
+                        loaderName,
+                        delegationSubject);
+
+            } catch (IOException ioe) {
+                communicatorAdmin.gotIOException(ioe);
+
+                return connection.createMBean(className,
+                        name,
+                        loaderName,
+                        delegationSubject);
+
+            } finally {
+                popDefaultClassLoader(old);
+            }
+        }
+
+        public ObjectInstance createMBean(String className,
+                ObjectName name,
+                Object params[],
+                String signature[])
+                throws ReflectionException,
+                InstanceAlreadyExistsException,
+                MBeanRegistrationException,
+                MBeanException,
+                NotCompliantMBeanException,
+                IOException {
+            if (logger.debugOn())
+                logger.debug("createMBean(String,ObjectName,Object[],String[])",
+                        "className=" + className + ", name="
+                        + name + ", signature=" + strings(signature));
+
+            final MarshalledObject<Object[]> sParams =
+                    new MarshalledObject<Object[]>(params);
+            final ClassLoader old = pushDefaultClassLoader();
+            try {
+                return connection.createMBean(className,
+                        name,
+                        sParams,
+                        signature,
+                        delegationSubject);
+            } catch (IOException ioe) {
+                communicatorAdmin.gotIOException(ioe);
+
+                return connection.createMBean(className,
+                        name,
+                        sParams,
+                        signature,
+                        delegationSubject);
+            } finally {
+                popDefaultClassLoader(old);
+            }
+        }
+
+        public ObjectInstance createMBean(String className,
+                ObjectName name,
+                ObjectName loaderName,
+                Object params[],
+                String signature[])
+                throws ReflectionException,
+                InstanceAlreadyExistsException,
+                MBeanRegistrationException,
+                MBeanException,
+                NotCompliantMBeanException,
+                InstanceNotFoundException,
+                IOException {
+            if (logger.debugOn()) logger.debug(
+                    "createMBean(String,ObjectName,ObjectName,Object[],String[])",
+                    "className=" + className + ", name=" + name + ", loaderName="
+                    + loaderName + ", signature=" + strings(signature));
+
+            final MarshalledObject<Object[]> sParams =
+                    new MarshalledObject<Object[]>(params);
+            final ClassLoader old = pushDefaultClassLoader();
+            try {
+                return connection.createMBean(className,
+                        name,
+                        loaderName,
+                        sParams,
+                        signature,
+                        delegationSubject);
+            } catch (IOException ioe) {
+                communicatorAdmin.gotIOException(ioe);
+
+                return connection.createMBean(className,
+                        name,
+                        loaderName,
+                        sParams,
+                        signature,
+                        delegationSubject);
+            } finally {
+                popDefaultClassLoader(old);
+            }
+        }
+
+        public void unregisterMBean(ObjectName name)
+        throws InstanceNotFoundException,
+                MBeanRegistrationException,
+                IOException {
+            if (logger.debugOn())
+                logger.debug("unregisterMBean", "name=" + name);
+
+            final ClassLoader old = pushDefaultClassLoader();
+            try {
+                connection.unregisterMBean(name, delegationSubject);
+            } catch (IOException ioe) {
+                communicatorAdmin.gotIOException(ioe);
+
+                connection.unregisterMBean(name, delegationSubject);
+            } finally {
+                popDefaultClassLoader(old);
+            }
+        }
+
+        public ObjectInstance getObjectInstance(ObjectName name)
+        throws InstanceNotFoundException,
+                IOException {
+            if (logger.debugOn())
+                logger.debug("getObjectInstance", "name=" + name);
+
+            final ClassLoader old = pushDefaultClassLoader();
+            try {
+                return connection.getObjectInstance(name, delegationSubject);
+            } catch (IOException ioe) {
+                communicatorAdmin.gotIOException(ioe);
+
+                return connection.getObjectInstance(name, delegationSubject);
+            } finally {
+                popDefaultClassLoader(old);
+            }
+        }
+
+        public Set<ObjectInstance> queryMBeans(ObjectName name,
+                QueryExp query)
+                throws IOException {
+            if (logger.debugOn()) logger.debug("queryMBeans",
+                    "name=" + name + ", query=" + query);
+
+            final MarshalledObject<QueryExp> sQuery =
+                    new MarshalledObject<QueryExp>(query);
+            final ClassLoader old = pushDefaultClassLoader();
+            try {
+                return connection.queryMBeans(name, sQuery, delegationSubject);
+            } catch (IOException ioe) {
+                communicatorAdmin.gotIOException(ioe);
+
+                return connection.queryMBeans(name, sQuery, delegationSubject);
+            } finally {
+                popDefaultClassLoader(old);
+            }
+        }
+
+        public Set<ObjectName> queryNames(ObjectName name,
+                QueryExp query)
+                throws IOException {
+            if (logger.debugOn()) logger.debug("queryNames",
+                    "name=" + name + ", query=" + query);
+
+            final MarshalledObject<QueryExp> sQuery =
+                    new MarshalledObject<QueryExp>(query);
+            final ClassLoader old = pushDefaultClassLoader();
+            try {
+                return connection.queryNames(name, sQuery, delegationSubject);
+            } catch (IOException ioe) {
+                communicatorAdmin.gotIOException(ioe);
+
+                return connection.queryNames(name, sQuery, delegationSubject);
+            } finally {
+                popDefaultClassLoader(old);
+            }
+        }
+
+        public boolean isRegistered(ObjectName name)
+        throws IOException {
+            if (logger.debugOn())
+                logger.debug("isRegistered", "name=" + name);
+
+            final ClassLoader old = pushDefaultClassLoader();
+            try {
+                return connection.isRegistered(name, delegationSubject);
+            } catch (IOException ioe) {
+                communicatorAdmin.gotIOException(ioe);
+
+                return connection.isRegistered(name, delegationSubject);
+            } finally {
+                popDefaultClassLoader(old);
+            }
+        }
+
+        public Integer getMBeanCount()
+        throws IOException {
+            if (logger.debugOn()) logger.debug("getMBeanCount", "");
+
+            final ClassLoader old = pushDefaultClassLoader();
+            try {
+                return connection.getMBeanCount(delegationSubject);
+            } catch (IOException ioe) {
+                communicatorAdmin.gotIOException(ioe);
+
+                return connection.getMBeanCount(delegationSubject);
+            } finally {
+                popDefaultClassLoader(old);
+            }
+        }
+
+        public Object getAttribute(ObjectName name,
+                String attribute)
+                throws MBeanException,
+                AttributeNotFoundException,
+                InstanceNotFoundException,
+                ReflectionException,
+                IOException {
+            if (logger.debugOn()) logger.debug("getAttribute",
+                    "name=" + name + ", attribute="
+                    + attribute);
+
+            final ClassLoader old = pushDefaultClassLoader();
+            try {
+                return connection.getAttribute(name,
+                        attribute,
+                        delegationSubject);
+            } catch (IOException ioe) {
+                communicatorAdmin.gotIOException(ioe);
+
+                return connection.getAttribute(name,
+                        attribute,
+                        delegationSubject);
+            } finally {
+                popDefaultClassLoader(old);
+            }
+        }
+
+        public AttributeList getAttributes(ObjectName name,
+                String[] attributes)
+                throws InstanceNotFoundException,
+                ReflectionException,
+                IOException {
+            if (logger.debugOn()) logger.debug("getAttributes",
+                    "name=" + name + ", attributes="
+                    + strings(attributes));
+
+            final ClassLoader old = pushDefaultClassLoader();
+            try {
+                return connection.getAttributes(name,
+                        attributes,
+                        delegationSubject);
+
+            } catch (IOException ioe) {
+                communicatorAdmin.gotIOException(ioe);
+
+                return connection.getAttributes(name,
+                        attributes,
+                        delegationSubject);
+            } finally {
+                popDefaultClassLoader(old);
+            }
+        }
+
+
+        public void setAttribute(ObjectName name,
+                Attribute attribute)
+                throws InstanceNotFoundException,
+                AttributeNotFoundException,
+                InvalidAttributeValueException,
+                MBeanException,
+                ReflectionException,
+                IOException {
+
+            if (logger.debugOn()) logger.debug("setAttribute",
+                    "name=" + name + ", attribute name="
+                    + attribute.getName());
+
+            final MarshalledObject<Attribute> sAttribute =
+                    new MarshalledObject<Attribute>(attribute);
+            final ClassLoader old = pushDefaultClassLoader();
+            try {
+                connection.setAttribute(name, sAttribute, delegationSubject);
+            } catch (IOException ioe) {
+                communicatorAdmin.gotIOException(ioe);
+
+                connection.setAttribute(name, sAttribute, delegationSubject);
+            } finally {
+                popDefaultClassLoader(old);
+            }
+        }
+
+        public AttributeList setAttributes(ObjectName name,
+                AttributeList attributes)
+                throws InstanceNotFoundException,
+                ReflectionException,
+                IOException {
+
+            if (logger.debugOn()) {
+                logger.debug("setAttributes",
+                    "name=" + name + ", attribute names="
+                    + getAttributesNames(attributes));
+            }
+
+            final MarshalledObject<AttributeList> sAttributes =
+                    new MarshalledObject<AttributeList>(attributes);
+            final ClassLoader old = pushDefaultClassLoader();
+            try {
+                return connection.setAttributes(name,
+                        sAttributes,
+                        delegationSubject);
+            } catch (IOException ioe) {
+                communicatorAdmin.gotIOException(ioe);
+
+                return connection.setAttributes(name,
+                        sAttributes,
+                        delegationSubject);
+            } finally {
+                popDefaultClassLoader(old);
+            }
+        }
+
+
+        public Object invoke(ObjectName name,
+                String operationName,
+                Object params[],
+                String signature[])
+                throws InstanceNotFoundException,
+                MBeanException,
+                ReflectionException,
+                IOException {
+
+            if (logger.debugOn()) logger.debug("invoke",
+                    "name=" + name
+                    + ", operationName=" + operationName
+                    + ", signature=" + strings(signature));
+
+            final MarshalledObject<Object[]> sParams =
+                    new MarshalledObject<Object[]>(params);
+            final ClassLoader old = pushDefaultClassLoader();
+            try {
+                return connection.invoke(name,
+                        operationName,
+                        sParams,
+                        signature,
+                        delegationSubject);
+            } catch (IOException ioe) {
+                communicatorAdmin.gotIOException(ioe);
+
+                return connection.invoke(name,
+                        operationName,
+                        sParams,
+                        signature,
+                        delegationSubject);
+            } finally {
+                popDefaultClassLoader(old);
+            }
+        }
+
+
+        public String getDefaultDomain()
+        throws IOException {
+            if (logger.debugOn()) logger.debug("getDefaultDomain", "");
+
+            final ClassLoader old = pushDefaultClassLoader();
+            try {
+                return connection.getDefaultDomain(delegationSubject);
+            } catch (IOException ioe) {
+                communicatorAdmin.gotIOException(ioe);
+
+                return connection.getDefaultDomain(delegationSubject);
+            } finally {
+                popDefaultClassLoader(old);
+            }
+        }
+
+        public String[] getDomains() throws IOException {
+            if (logger.debugOn()) logger.debug("getDomains", "");
+
+            final ClassLoader old = pushDefaultClassLoader();
+            try {
+                return connection.getDomains(delegationSubject);
+            } catch (IOException ioe) {
+                communicatorAdmin.gotIOException(ioe);
+
+                return connection.getDomains(delegationSubject);
+            } finally {
+                popDefaultClassLoader(old);
+            }
+        }
+
+        public MBeanInfo getMBeanInfo(ObjectName name)
+        throws InstanceNotFoundException,
+                IntrospectionException,
+                ReflectionException,
+                IOException {
+
+            if (logger.debugOn()) logger.debug("getMBeanInfo", "name=" + name);
+            final ClassLoader old = pushDefaultClassLoader();
+            try {
+                return connection.getMBeanInfo(name, delegationSubject);
+            } catch (IOException ioe) {
+                communicatorAdmin.gotIOException(ioe);
+
+                return connection.getMBeanInfo(name, delegationSubject);
+            } finally {
+                popDefaultClassLoader(old);
+            }
+        }
+
+
+        public boolean isInstanceOf(ObjectName name,
+                String className)
+                throws InstanceNotFoundException,
+                IOException {
+            if (logger.debugOn())
+                logger.debug("isInstanceOf", "name=" + name +
+                        ", className=" + className);
+
+            final ClassLoader old = pushDefaultClassLoader();
+            try {
+                return connection.isInstanceOf(name,
+                        className,
+                        delegationSubject);
+            } catch (IOException ioe) {
+                communicatorAdmin.gotIOException(ioe);
+
+                return connection.isInstanceOf(name,
+                        className,
+                        delegationSubject);
+            } finally {
+                popDefaultClassLoader(old);
+            }
+        }
+
+        public void addNotificationListener(ObjectName name,
+                ObjectName listener,
+                NotificationFilter filter,
+                Object handback)
+                throws InstanceNotFoundException,
+                IOException {
+
+            if (logger.debugOn())
+                logger.debug("addNotificationListener" +
+                        "(ObjectName,ObjectName,NotificationFilter,Object)",
+                        "name=" + name + ", listener=" + listener
+                        + ", filter=" + filter + ", handback=" + handback);
+
+            final MarshalledObject<NotificationFilter> sFilter =
+                    new MarshalledObject<NotificationFilter>(filter);
+            final MarshalledObject<Object> sHandback =
+                    new MarshalledObject<Object>(handback);
+            final ClassLoader old = pushDefaultClassLoader();
+            try {
+                connection.addNotificationListener(name,
+                        listener,
+                        sFilter,
+                        sHandback,
+                        delegationSubject);
+            } catch (IOException ioe) {
+                communicatorAdmin.gotIOException(ioe);
+
+                connection.addNotificationListener(name,
+                        listener,
+                        sFilter,
+                        sHandback,
+                        delegationSubject);
+            } finally {
+                popDefaultClassLoader(old);
+            }
+        }
+
+        public void removeNotificationListener(ObjectName name,
+                ObjectName listener)
+                throws InstanceNotFoundException,
+                ListenerNotFoundException,
+                IOException {
+
+            if (logger.debugOn()) logger.debug("removeNotificationListener" +
+                    "(ObjectName,ObjectName)",
+                    "name=" + name
+                    + ", listener=" + listener);
+
+            final ClassLoader old = pushDefaultClassLoader();
+            try {
+                connection.removeNotificationListener(name,
+                        listener,
+                        delegationSubject);
+            } catch (IOException ioe) {
+                communicatorAdmin.gotIOException(ioe);
+
+                connection.removeNotificationListener(name,
+                        listener,
+                        delegationSubject);
+            } finally {
+                popDefaultClassLoader(old);
+            }
+        }
+
+        public void removeNotificationListener(ObjectName name,
+                ObjectName listener,
+                NotificationFilter filter,
+                Object handback)
+                throws InstanceNotFoundException,
+                ListenerNotFoundException,
+                IOException {
+            if (logger.debugOn())
+                logger.debug("removeNotificationListener" +
+                        "(ObjectName,ObjectName,NotificationFilter,Object)",
+                        "name=" + name
+                        + ", listener=" + listener
+                        + ", filter=" + filter
+                        + ", handback=" + handback);
+
+            final MarshalledObject<NotificationFilter> sFilter =
+                    new MarshalledObject<NotificationFilter>(filter);
+            final MarshalledObject<Object> sHandback =
+                    new MarshalledObject<Object>(handback);
+            final ClassLoader old = pushDefaultClassLoader();
+            try {
+                connection.removeNotificationListener(name,
+                        listener,
+                        sFilter,
+                        sHandback,
+                        delegationSubject);
+            } catch (IOException ioe) {
+                communicatorAdmin.gotIOException(ioe);
+
+                connection.removeNotificationListener(name,
+                        listener,
+                        sFilter,
+                        sHandback,
+                        delegationSubject);
+            } finally {
+                popDefaultClassLoader(old);
+            }
+        }
+
+        // Specific Notification Handle ----------------------------------
+
+        public void addNotificationListener(ObjectName name,
+                NotificationListener listener,
+                NotificationFilter filter,
+                Object handback)
+                throws InstanceNotFoundException,
+                IOException {
+
+            final boolean debug = logger.debugOn();
+
+            if (debug)
+                logger.debug("addNotificationListener" +
+                        "(ObjectName,NotificationListener,"+
+                        "NotificationFilter,Object)",
+                        "name=" + name
+                        + ", listener=" + listener
+                        + ", filter=" + filter
+                        + ", handback=" + handback);
+
+            final Integer listenerID =
+                    addListenerWithSubject(name,
+                    new MarshalledObject<NotificationFilter>(filter),
+                    delegationSubject,true);
+            rmiNotifClient.addNotificationListener(listenerID, name, listener,
+                    filter, handback,
+                    delegationSubject);
+        }
+
+        public void removeNotificationListener(ObjectName name,
+                NotificationListener listener)
+                throws InstanceNotFoundException,
+                ListenerNotFoundException,
+                IOException {
+
+            final boolean debug = logger.debugOn();
+
+            if (debug) logger.debug("removeNotificationListener"+
+                    "(ObjectName,NotificationListener)",
+                    "name=" + name
+                    + ", listener=" + listener);
+
+            final Integer[] ret =
+                    rmiNotifClient.removeNotificationListener(name, listener);
+
+            if (debug) logger.debug("removeNotificationListener",
+                    "listenerIDs=" + objects(ret));
+
+            final ClassLoader old = pushDefaultClassLoader();
+
+            try {
+                connection.removeNotificationListeners(name,
+                        ret,
+                        delegationSubject);
+            } catch (IOException ioe) {
+                communicatorAdmin.gotIOException(ioe);
+
+                connection.removeNotificationListeners(name,
+                        ret,
+                        delegationSubject);
+            } finally {
+                popDefaultClassLoader(old);
+            }
+
+        }
+
+        public void removeNotificationListener(ObjectName name,
+                NotificationListener listener,
+                NotificationFilter filter,
+                Object handback)
+                throws InstanceNotFoundException,
+                ListenerNotFoundException,
+                IOException {
+            final boolean debug = logger.debugOn();
+
+            if (debug)
+                logger.debug("removeNotificationListener"+
+                        "(ObjectName,NotificationListener,"+
+                        "NotificationFilter,Object)",
+                        "name=" + name
+                        + ", listener=" + listener
+                        + ", filter=" + filter
+                        + ", handback=" + handback);
+
+            final Integer ret =
+                    rmiNotifClient.removeNotificationListener(name, listener,
+                    filter, handback);
+
+            if (debug) logger.debug("removeNotificationListener",
+                    "listenerID=" + ret);
+
+            final ClassLoader old = pushDefaultClassLoader();
+            try {
+                connection.removeNotificationListeners(name,
+                        new Integer[] {ret},
+                        delegationSubject);
+            } catch (IOException ioe) {
+                communicatorAdmin.gotIOException(ioe);
+
+                connection.removeNotificationListeners(name,
+                        new Integer[] {ret},
+                        delegationSubject);
+            } finally {
+                popDefaultClassLoader(old);
+            }
+
+        }
+    }
+
+    //--------------------------------------------------------------------
+    private class RMINotifClient extends ClientNotifForwarder {
+        public RMINotifClient(ClassLoader cl, Map<String, ?> env) {
+            super(cl, env);
+        }
+
+        protected NotificationResult fetchNotifs(long clientSequenceNumber,
+                int maxNotifications,
+                long timeout)
+                throws IOException, ClassNotFoundException {
+
+            boolean retried = false;
+            while (true) { // used for a successful re-connection
+                           // or a transient network problem
+                try {
+                    return connection.fetchNotifications(clientSequenceNumber,
+                            maxNotifications,
+                            timeout); // return normally
+                } catch (IOException ioe) {
+                    // Examine the chain of exceptions to determine whether this
+                    // is a deserialization issue. If so - we propagate the
+                    // appropriate exception to the caller, who will then
+                    // proceed with fetching notifications one by one
+                    rethrowDeserializationException(ioe);
+
+                    try {
+                        communicatorAdmin.gotIOException(ioe);
+                        // reconnection OK, back to "while" to do again
+                    } catch (IOException ee) {
+                        boolean toClose = false;
+
+                        synchronized (this) {
+                            if (terminated) {
+                                // the connection is closed.
+                                throw ioe;
+                            } else if (retried) {
+                                toClose = true;
+                            }
+                        }
+
+                        if (toClose) {
+                            // JDK-8049303
+                            // We received an IOException - but the communicatorAdmin
+                            // did not close the connection - possibly because
+                            // the original exception was raised by a transient network
+                            // problem?
+                            // We already know that this exception is not due to a deserialization
+                            // issue as we already took care of that before involving the
+                            // communicatorAdmin. Moreover - we already made one retry attempt
+                            // at fetching the same batch of notifications - and the
+                            // problem persisted.
+                            // Since trying again doesn't seem to solve the issue, we will now
+                            // close the connection. Doing otherwise might cause the
+                            // NotifFetcher thread to die silently.
+                            final Notification failedNotif =
+                                    new JMXConnectionNotification(
+                                    JMXConnectionNotification.FAILED,
+                                    this,
+                                    connectionId,
+                                    clientNotifSeqNo++,
+                                    "Failed to communicate with the server: " + ioe.toString(),
+                                    ioe);
+
+                            sendNotification(failedNotif);
+
+                            try {
+                                close(true);
+                            } catch (Exception e) {
+                                // OK.
+                                // We are closing
+                            }
+                            throw ioe; // the connection is closed here.
+                        } else {
+                            // JDK-8049303 possible transient network problem,
+                            // let's try one more time
+                            retried = true;
+                        }
+                    }
+                }
+            }
+        }
+
+        private void rethrowDeserializationException(IOException ioe)
+                throws ClassNotFoundException, IOException {
+            // specially treating for an UnmarshalException
+            if (ioe instanceof UnmarshalException) {
+                NotSerializableException nse = new NotSerializableException();
+                nse.initCause(ioe);
+                throw nse; // the fix of 6937053 made ClientNotifForwarder.fetchNotifs
+                           // fetch one by one with UnmarshalException
+            }
+
+            // Not serialization problem, return.
+        }
+
+        protected Integer addListenerForMBeanRemovedNotif()
+        throws IOException, InstanceNotFoundException {
+            NotificationFilterSupport clientFilter =
+                    new NotificationFilterSupport();
+            clientFilter.enableType(
+                    MBeanServerNotification.UNREGISTRATION_NOTIFICATION);
+            MarshalledObject<NotificationFilter> sFilter =
+                new MarshalledObject<NotificationFilter>(clientFilter);
+
+            Integer[] listenerIDs;
+            final ObjectName[] names =
+                new ObjectName[] {MBeanServerDelegate.DELEGATE_NAME};
+            final MarshalledObject<NotificationFilter>[] filters =
+                Util.cast(new MarshalledObject<?>[] {sFilter});
+            final Subject[] subjects = new Subject[] {null};
+            try {
+                listenerIDs =
+                        connection.addNotificationListeners(names,
+                        filters,
+                        subjects);
+
+            } catch (IOException ioe) {
+                communicatorAdmin.gotIOException(ioe);
+
+                listenerIDs =
+                        connection.addNotificationListeners(names,
+                        filters,
+                        subjects);
+            }
+            return listenerIDs[0];
+        }
+
+        protected void removeListenerForMBeanRemovedNotif(Integer id)
+        throws IOException, InstanceNotFoundException,
+                ListenerNotFoundException {
+            try {
+                connection.removeNotificationListeners(
+                        MBeanServerDelegate.DELEGATE_NAME,
+                        new Integer[] {id},
+                        null);
+            } catch (IOException ioe) {
+                communicatorAdmin.gotIOException(ioe);
+
+                connection.removeNotificationListeners(
+                        MBeanServerDelegate.DELEGATE_NAME,
+                        new Integer[] {id},
+                        null);
+            }
+
+        }
+
+        protected void lostNotifs(String message, long number) {
+            final String notifType = JMXConnectionNotification.NOTIFS_LOST;
+
+            final JMXConnectionNotification n =
+                new JMXConnectionNotification(notifType,
+                                              RMIConnector.this,
+                                              connectionId,
+                                              clientNotifCounter++,
+                                              message,
+                                              Long.valueOf(number));
+            sendNotification(n);
+        }
+    }
+
+    private class RMIClientCommunicatorAdmin extends ClientCommunicatorAdmin {
+        public RMIClientCommunicatorAdmin(long period) {
+            super(period);
+        }
+
+        @Override
+        public void gotIOException(IOException ioe) throws IOException {
+            if (ioe instanceof NoSuchObjectException) {
+                // need to restart
+                super.gotIOException(ioe);
+
+                return;
+            }
+
+            // check if the connection is broken
+            try {
+                connection.getDefaultDomain(null);
+            } catch (IOException ioexc) {
+                boolean toClose = false;
+
+                synchronized(this) {
+                    if (!terminated) {
+                        terminated = true;
+
+                        toClose = true;
+                    }
+                }
+
+                if (toClose) {
+                    // we should close the connection,
+                    // but send a failed notif at first
+                    final Notification failedNotif =
+                            new JMXConnectionNotification(
+                            JMXConnectionNotification.FAILED,
+                            this,
+                            connectionId,
+                            clientNotifSeqNo++,
+                            "Failed to communicate with the server: "+ioe.toString(),
+                            ioe);
+
+                    sendNotification(failedNotif);
+
+                    try {
+                        close(true);
+                    } catch (Exception e) {
+                        // OK.
+                        // We are closing
+                    }
+                }
+            }
+
+            // forward the exception
+            if (ioe instanceof ServerException) {
+                /* Need to unwrap the exception.
+                   Some user-thrown exception at server side will be wrapped by
+                   rmi into a ServerException.
+                   For example, a RMIConnnectorServer will wrap a
+                   ClassNotFoundException into a UnmarshalException, and rmi
+                   will throw a ServerException at client side which wraps this
+                   UnmarshalException.
+                   No failed notif here.
+                 */
+                Throwable tt = ((ServerException)ioe).detail;
+
+                if (tt instanceof IOException) {
+                    throw (IOException)tt;
+                } else if (tt instanceof RuntimeException) {
+                    throw (RuntimeException)tt;
+                }
+            }
+
+            throw ioe;
+        }
+
+        public void reconnectNotificationListeners(ClientListenerInfo[] old) throws IOException {
+            final int len  = old.length;
+            int i;
+
+            ClientListenerInfo[] clis = new ClientListenerInfo[len];
+
+            final Subject[] subjects = new Subject[len];
+            final ObjectName[] names = new ObjectName[len];
+            final NotificationListener[] listeners = new NotificationListener[len];
+            final NotificationFilter[] filters = new NotificationFilter[len];
+            final MarshalledObject<NotificationFilter>[] mFilters =
+                    Util.cast(new MarshalledObject<?>[len]);
+            final Object[] handbacks = new Object[len];
+
+            for (i=0;i<len;i++) {
+                subjects[i]  = old[i].getDelegationSubject();
+                names[i]     = old[i].getObjectName();
+                listeners[i] = old[i].getListener();
+                filters[i]   = old[i].getNotificationFilter();
+                mFilters[i]  = new MarshalledObject<NotificationFilter>(filters[i]);
+                handbacks[i] = old[i].getHandback();
+            }
+
+            try {
+                Integer[] ids = addListenersWithSubjects(names,mFilters,subjects,false);
+
+                for (i=0;i<len;i++) {
+                    clis[i] = new ClientListenerInfo(ids[i],
+                            names[i],
+                            listeners[i],
+                            filters[i],
+                            handbacks[i],
+                            subjects[i]);
+                }
+
+                rmiNotifClient.postReconnection(clis);
+
+                return;
+            } catch (InstanceNotFoundException infe) {
+                // OK, we will do one by one
+            }
+
+            int j = 0;
+            for (i=0;i<len;i++) {
+                try {
+                    Integer id = addListenerWithSubject(names[i],
+                            new MarshalledObject<NotificationFilter>(filters[i]),
+                            subjects[i],
+                            false);
+
+                    clis[j++] = new ClientListenerInfo(id,
+                            names[i],
+                            listeners[i],
+                            filters[i],
+                            handbacks[i],
+                            subjects[i]);
+                } catch (InstanceNotFoundException infe) {
+                    logger.warning("reconnectNotificationListeners",
+                            "Can't reconnect listener for " +
+                            names[i]);
+                }
+            }
+
+            if (j != len) {
+                ClientListenerInfo[] tmp = clis;
+                clis = new ClientListenerInfo[j];
+                System.arraycopy(tmp, 0, clis, 0, j);
+            }
+
+            rmiNotifClient.postReconnection(clis);
+        }
+
+        protected void checkConnection() throws IOException {
+            if (logger.debugOn())
+                logger.debug("RMIClientCommunicatorAdmin-checkConnection",
+                        "Calling the method getDefaultDomain.");
+
+            connection.getDefaultDomain(null);
+        }
+
+        protected void doStart() throws IOException {
+            // Get RMIServer stub from directory or URL encoding if needed.
+            RMIServer stub;
+            try {
+                stub = (rmiServer!=null)?rmiServer:
+                    findRMIServer(jmxServiceURL, env);
+            } catch (NamingException ne) {
+                throw new IOException("Failed to get a RMI stub: "+ne);
+            }
+
+            // Calling newClient on the RMIServer stub.
+            Object credentials = env.get(CREDENTIALS);
+            connection = stub.newClient(credentials);
+
+            // notif issues
+            final ClientListenerInfo[] old = rmiNotifClient.preReconnection();
+
+            reconnectNotificationListeners(old);
+
+            connectionId = getConnectionId();
+
+            Notification reconnectedNotif =
+                    new JMXConnectionNotification(JMXConnectionNotification.OPENED,
+                    this,
+                    connectionId,
+                    clientNotifSeqNo++,
+                    "Reconnected to server",
+                    null);
+            sendNotification(reconnectedNotif);
+
+        }
+
+        protected void doStop() {
+            try {
+                close();
+            } catch (IOException ioe) {
+                logger.warning("RMIClientCommunicatorAdmin-doStop",
+                        "Failed to call the method close():" + ioe);
+                logger.debug("RMIClientCommunicatorAdmin-doStop",ioe);
+            }
+        }
+    }
+
+    //--------------------------------------------------------------------
+    // Private stuff - Serialization
+    //--------------------------------------------------------------------
+    /**
+     * Read RMIConnector fields from an {@link java.io.ObjectInputStream
+     * ObjectInputStream}.
+     * Calls {@code s.defaultReadObject()} and then initializes
+     * all transient variables that need initializing.
+     * @param s The ObjectInputStream to read from.
+     * @exception InvalidObjectException if none of <var>rmiServer</var> stub
+     *    or <var>jmxServiceURL</var> are set.
+     * @see #RMIConnector(JMXServiceURL,Map)
+     * @see #RMIConnector(RMIServer,Map)
+     **/
+    private void readObject(java.io.ObjectInputStream s)
+    throws IOException, ClassNotFoundException  {
+        s.defaultReadObject();
+
+        if (rmiServer == null && jmxServiceURL == null) throw new
+                InvalidObjectException("rmiServer and jmxServiceURL both null");
+
+        initTransients();
+    }
+
+    /**
+     * Writes the RMIConnector fields to an {@link java.io.ObjectOutputStream
+     * ObjectOutputStream}.
+     * <p>Connects the underlying RMIServer stub to an ORB, if needed,
+     * before serializing it. This is done using the environment
+     * map that was provided to the constructor, if any, and as documented
+     * in {@link javax.management.remote.rmi}.</p>
+     * <p>This method then calls {@code s.defaultWriteObject()}.
+     * Usually, <var>rmiServer</var> is null if this object
+     * was constructed with a JMXServiceURL, and <var>jmxServiceURL</var>
+     * is null if this object is constructed with a RMIServer stub.
+     * <p>Note that the environment Map is not serialized, since the objects
+     * it contains are assumed to be contextual and relevant only
+     * with respect to the local environment (class loader, ORB, etc...).</p>
+     * <p>After an RMIConnector is deserialized, it is assumed that the
+     * user will call {@link #connect(Map)}, providing a new Map that
+     * can contain values which are contextually relevant to the new
+     * local environment.</p>
+     * <p>Since connection to the ORB is needed prior to serializing, and
+     * since the ORB to connect to is one of those contextual parameters,
+     * it is not recommended to re-serialize a just de-serialized object -
+     * as the de-serialized object has no map. Thus, when an RMIConnector
+     * object is needed for serialization or transmission to a remote
+     * application, it is recommended to obtain a new RMIConnector stub
+     * by calling {@link RMIConnectorServer#toJMXConnector(Map)}.</p>
+     * @param s The ObjectOutputStream to write to.
+     * @exception InvalidObjectException if none of <var>rmiServer</var> stub
+     *    or <var>jmxServiceURL</var> are set.
+     * @see #RMIConnector(JMXServiceURL,Map)
+     * @see #RMIConnector(RMIServer,Map)
+     **/
+    private void writeObject(java.io.ObjectOutputStream s)
+    throws IOException {
+        if (rmiServer == null && jmxServiceURL == null) throw new
+                InvalidObjectException("rmiServer and jmxServiceURL both null.");
+        s.defaultWriteObject();
+    }
+
+    // Initialization of transient variables.
+    private void initTransients() {
+        rmbscMap = new WeakHashMap<Subject, WeakReference<MBeanServerConnection>>();
+        connected = false;
+        terminated = false;
+
+        connectionBroadcaster = new NotificationBroadcasterSupport();
+    }
+
+    //--------------------------------------------------------------------
+    // Private stuff - Check if stub can be trusted.
+    //--------------------------------------------------------------------
+
+    private static void checkStub(Remote stub,
+            Class<?> stubClass) {
+
+        // Check remote stub is from the expected class.
+        //
+        if (stub.getClass() != stubClass) {
+            if (!Proxy.isProxyClass(stub.getClass())) {
+                throw new SecurityException(
+                        "Expecting a " + stubClass.getName() + " stub!");
+            } else {
+                InvocationHandler handler = Proxy.getInvocationHandler(stub);
+                if (handler.getClass() != RemoteObjectInvocationHandler.class)
+                    throw new SecurityException(
+                            "Expecting a dynamic proxy instance with a " +
+                            RemoteObjectInvocationHandler.class.getName() +
+                            " invocation handler!");
+                else
+                    stub = (Remote) handler;
+            }
+        }
+
+        // Check RemoteRef in stub is from the expected class
+        // "sun.rmi.server.UnicastRef2".
+        //
+        RemoteRef ref = ((RemoteObject)stub).getRef();
+        if (ref.getClass() != UnicastRef2.class)
+            throw new SecurityException(
+                    "Expecting a " + UnicastRef2.class.getName() +
+                    " remote reference in stub!");
+
+        // Check RMIClientSocketFactory in stub is from the expected class
+        // "javax.rmi.ssl.SslRMIClientSocketFactory".
+        //
+        LiveRef liveRef = ((UnicastRef2)ref).getLiveRef();
+        RMIClientSocketFactory csf = liveRef.getClientSocketFactory();
+        if (csf == null || csf.getClass() != SslRMIClientSocketFactory.class)
+            throw new SecurityException(
+                    "Expecting a " + SslRMIClientSocketFactory.class.getName() +
+                    " RMI client socket factory in stub!");
+    }
+
+    //--------------------------------------------------------------------
+    // Private stuff - RMIServer creation
+    //--------------------------------------------------------------------
+
+    private RMIServer findRMIServer(JMXServiceURL directoryURL,
+            Map<String, Object> environment)
+            throws NamingException, IOException {
+
+        String path = directoryURL.getURLPath();
+        int end = path.indexOf(';');
+        if (end < 0) end = path.length();
+        if (path.startsWith("/jndi/"))
+            return findRMIServerJNDI(path.substring(6,end), environment);
+        else if (path.startsWith("/stub/"))
+            return findRMIServerJRMP(path.substring(6,end), environment);
+        else {
+            final String msg = "URL path must begin with /jndi/ or /stub/ " +
+                    "or /ior/: " + path;
+            throw new MalformedURLException(msg);
+        }
+    }
+
+    /**
+     * Lookup the RMIServer stub in a directory.
+     * @param jndiURL A JNDI URL indicating the location of the Stub
+     *                (see {@link javax.management.remote.rmi}), e.g.:
+     *   <ul><li>{@code rmi://registry-host:port/rmi-stub-name}</li>
+     *       <li>or {@code ldap://ldap-host:port/java-container-dn}</li>
+     *   </ul>
+     * @param env the environment Map passed to the connector.
+     * @return The retrieved RMIServer stub.
+     * @exception NamingException if the stub couldn't be found.
+     **/
+    private RMIServer findRMIServerJNDI(String jndiURL, Map<String, ?> env)
+            throws NamingException {
+
+        InitialContext ctx = new InitialContext(EnvHelp.mapToHashtable(env));
+
+        Object objref = ctx.lookup(jndiURL);
+        ctx.close();
+
+        return narrowJRMPServer(objref);
+    }
+
+    private static RMIServer narrowJRMPServer(Object objref) {
+
+        return (RMIServer) objref;
+    }
+
+    private RMIServer findRMIServerJRMP(String base64, Map<String, ?> env)
+        throws IOException {
+        final byte[] serialized;
+        try {
+            serialized = base64ToByteArray(base64);
+        } catch (IllegalArgumentException e) {
+            throw new MalformedURLException("Bad BASE64 encoding: " +
+                    e.getMessage());
+        }
+        final ByteArrayInputStream bin = new ByteArrayInputStream(serialized);
+
+        final ClassLoader loader = EnvHelp.resolveClientClassLoader(env);
+        final ObjectInputStream oin =
+                (loader == null) ?
+                    new ObjectInputStream(bin) :
+                    new ObjectInputStreamWithLoader(bin, loader);
+        final Object stub;
+        try {
+            stub = oin.readObject();
+        } catch (ClassNotFoundException e) {
+            throw new MalformedURLException("Class not found: " + e);
+        }
+        return (RMIServer)stub;
+    }
+
+    private static final class ObjectInputStreamWithLoader
+            extends ObjectInputStream {
+        ObjectInputStreamWithLoader(InputStream in, ClassLoader cl)
+        throws IOException, IllegalArgumentException {
+            super(in);
+            if (cl == null ) {
+              throw new IllegalArgumentException("class loader is null");
+            }
+            this.loader = cl;
+        }
+
+        @Override
+        protected Class<?> resolveClass(ObjectStreamClass classDesc)
+                throws IOException, ClassNotFoundException {
+            String name = classDesc.getName();
+            ReflectUtil.checkPackageAccess(name);
+            return Class.forName(name, false, Objects.requireNonNull(loader));
+        }
+
+        private final ClassLoader loader;
+    }
+
+    private MBeanServerConnection getConnectionWithSubject(Subject delegationSubject) {
+        MBeanServerConnection conn = null;
+
+        if (delegationSubject == null) {
+            if (nullSubjectConnRef == null
+                    || (conn = nullSubjectConnRef.get()) == null) {
+                conn = new RemoteMBeanServerConnection(null);
+                nullSubjectConnRef = new WeakReference<MBeanServerConnection>(conn);
+            }
+        } else {
+            WeakReference<MBeanServerConnection> wr = rmbscMap.get(delegationSubject);
+            if (wr == null || (conn = wr.get()) == null) {
+                conn = new RemoteMBeanServerConnection(delegationSubject);
+                rmbscMap.put(delegationSubject, new WeakReference<MBeanServerConnection>(conn));
+            }
+        }
+        return conn;
+    }
+
+    /*
+       The following section of code avoids a class loading problem
+       with RMI.  The problem is that an RMI stub, when deserializing
+       a remote method return value or exception, will first of all
+       consult the first non-bootstrap class loader it finds in the
+       call stack.  This can lead to behavior that is not portable
+       between implementations of the JMX Remote API.  Notably, an
+       implementation on J2SE 1.4 will find the RMI stub's loader on
+       the stack.  But in J2SE 5, this stub is loaded by the
+       bootstrap loader, so RMI will find the loader of the user code
+       that called an MBeanServerConnection method.
+
+       To avoid this problem, we take advantage of what the RMI stub
+       is doing internally.  Each remote call will end up calling
+       ref.invoke(...), where ref is the RemoteRef parameter given to
+       the RMI stub's constructor.  It is within this call that the
+       deserialization will happen.  So we fabricate our own RemoteRef
+       that delegates everything to the "real" one but that is loaded
+       by a class loader that knows no other classes.  The class
+       loader NoCallStackClassLoader does this: the RemoteRef is an
+       instance of the class named by proxyRefClassName, which is
+       fabricated by the class loader using byte code that is defined
+       by the string below.
+
+       The call stack when the deserialization happens is thus this:
+       MBeanServerConnection.getAttribute (or whatever)
+       -> RMIConnectionImpl_Stub.getAttribute
+          -> ProxyRef.invoke(...getAttribute...)
+             -> UnicastRef.invoke(...getAttribute...)
+                -> internal RMI stuff
+
+       Here UnicastRef is the RemoteRef created when the stub was
+       deserialized (which is of some RMI internal class).  It and the
+       "internal RMI stuff" are loaded by the bootstrap loader, so are
+       transparent to the stack search.  The first non-bootstrap
+       loader found is our ProxyRefLoader, as required.
+
+       In a future version of this code as integrated into J2SE 5,
+       this workaround could be replaced by direct access to the
+       internals of RMI.  For now, we use the same code base for J2SE
+       and for the standalone Reference Implementation.
+
+       The byte code below encodes the following class, compiled using
+       J2SE 1.4.2 with the -g:none option.
+
+        package jdk.jmx.remote.internal.rmi;
+
+        import java.lang.reflect.Method;
+        import java.rmi.Remote;
+        import java.rmi.server.RemoteRef;
+        import com.sun.jmx.remote.internal.rmi.ProxyRef;
+
+        public class PRef extends ProxyRef {
+            public PRef(RemoteRef ref) {
+                super(ref);
+            }
+
+            public Object invoke(Remote obj, Method method,
+                                 Object[] params, long opnum)
+                    throws Exception {
+                return ref.invoke(obj, method, params, opnum);
+            }
+        }
+     */
+
+    private static final String rmiServerImplStubClassName =
+        RMIServer.class.getName() + "Impl_Stub";
+    private static final Class<?> rmiServerImplStubClass;
+    private static final String rmiConnectionImplStubClassName =
+            RMIConnection.class.getName() + "Impl_Stub";
+    private static final Class<?> rmiConnectionImplStubClass;
+    private static final String pRefClassName =
+        "jdk.jmx.remote.internal.rmi.PRef";
+    private static final Constructor<?> proxyRefConstructor;
+    static {
+        final String pRefByteCodeString =
+                "\312\376\272\276\0\0\0\65\0\27\12\0\5\0\15\11\0\4\0\16\13\0\17"+
+                "\0\20\7\0\21\7\0\22\1\0\6<init>\1\0\36(Ljava/rmi/server/Remote"+
+                "Ref;)V\1\0\4Code\1\0\6invoke\1\0S(Ljava/rmi/Remote;Ljava/lang/"+
+                "reflect/Method;[Ljava/lang/Object;J)Ljava/lang/Object;\1\0\12E"+
+                "xceptions\7\0\23\14\0\6\0\7\14\0\24\0\25\7\0\26\14\0\11\0\12\1"+
+                "\0 jdk/jmx/remote/internal/rmi/PRef\1\0(com/sun/jmx/remote/int"+
+                "ernal/rmi/ProxyRef\1\0\23java/lang/Exception\1\0\3ref\1\0\33Lj"+
+                "ava/rmi/server/RemoteRef;\1\0\31java/rmi/server/RemoteRef\0!\0"+
+                "\4\0\5\0\0\0\0\0\2\0\1\0\6\0\7\0\1\0\10\0\0\0\22\0\2\0\2\0\0\0"+
+                "\6*+\267\0\1\261\0\0\0\0\0\1\0\11\0\12\0\2\0\10\0\0\0\33\0\6\0"+
+                "\6\0\0\0\17*\264\0\2+,-\26\4\271\0\3\6\0\260\0\0\0\0\0\13\0\0\0"+
+                "\4\0\1\0\14\0\0";
+        final byte[] pRefByteCode =
+                NoCallStackClassLoader.stringToBytes(pRefByteCodeString);
+        PrivilegedExceptionAction<Constructor<?>> action =
+                new PrivilegedExceptionAction<Constructor<?>>() {
+            public Constructor<?> run() throws Exception {
+                Class<RMIConnector> thisClass = RMIConnector.class;
+                ClassLoader thisLoader = thisClass.getClassLoader();
+                ProtectionDomain thisProtectionDomain =
+                        thisClass.getProtectionDomain();
+
+                String proxyRefCName = ProxyRef.class.getName();
+                ClassLoader cl =
+                        new NoCallStackClassLoader(pRefClassName,
+                        pRefByteCode,
+                        new String[] { proxyRefCName },
+                        thisLoader,
+                        thisProtectionDomain);
+
+                Module jmxModule = ProxyRef.class.getModule();
+                Module rmiModule = RemoteRef.class.getModule();
+
+                String pkg = packageOf(pRefClassName);
+                assert pkg != null && pkg.length() > 0 && !pkg.equals(packageOf(proxyRefCName));
+                Module m = Modules.defineModule(cl, "jdk.remoteref", Collections.singleton(pkg));
+
+                // jdk.remoteref needs to read to java.base and jmxModule
+                Modules.addReads(m, Object.class.getModule());
+                Modules.addReads(m, jmxModule);
+                Modules.addReads(m, rmiModule);
+
+                // jdk.remoteref needs access to ProxyRef class
+                Modules.addExports(jmxModule, packageOf(proxyRefCName), m);
+
+                // java.management needs to instantiate the fabricated RemoteRef class
+                Modules.addReads(jmxModule, m);
+                Modules.addExports(m, pkg, jmxModule);
+
+                Class<?> c = cl.loadClass(pRefClassName);
+                return c.getConstructor(RemoteRef.class);
+            }
+        };
+
+        Class<?> serverStubClass;
+        try {
+            serverStubClass = Class.forName(rmiServerImplStubClassName);
+        } catch (Exception e) {
+            logger.error("<clinit>",
+                    "Failed to instantiate " +
+                    rmiServerImplStubClassName + ": " + e);
+            logger.debug("<clinit>",e);
+            serverStubClass = null;
+        }
+        rmiServerImplStubClass = serverStubClass;
+
+        Class<?> stubClass;
+        Constructor<?> constr;
+        try {
+            stubClass = Class.forName(rmiConnectionImplStubClassName);
+            constr = (Constructor<?>) AccessController.doPrivileged(action);
+        } catch (Exception e) {
+            logger.error("<clinit>",
+                    "Failed to initialize proxy reference constructor "+
+                    "for " + rmiConnectionImplStubClassName + ": " + e);
+            logger.debug("<clinit>",e);
+            stubClass = null;
+            constr = null;
+        }
+        rmiConnectionImplStubClass = stubClass;
+        proxyRefConstructor = constr;
+    }
+
+    private static String packageOf(String cn) {
+        int i = cn.lastIndexOf('.');
+        return i > 0 ? cn.substring(0, i) : "";
+    }
+
+    private static RMIConnection shadowJrmpStub(RemoteObject stub)
+    throws InstantiationException, IllegalAccessException,
+            InvocationTargetException, ClassNotFoundException,
+            NoSuchMethodException {
+        RemoteRef ref = stub.getRef();
+        RemoteRef proxyRef = (RemoteRef)
+            proxyRefConstructor.newInstance(new Object[] {ref});
+        final Constructor<?> rmiConnectionImplStubConstructor =
+            rmiConnectionImplStubClass.getConstructor(RemoteRef.class);
+        Object[] args = {proxyRef};
+        RMIConnection proxyStub = (RMIConnection)
+        rmiConnectionImplStubConstructor.newInstance(args);
+        return proxyStub;
+    }
+
+    private static RMIConnection getConnection(RMIServer server,
+            Object credentials,
+            boolean checkStub)
+            throws IOException {
+        RMIConnection c = server.newClient(credentials);
+        if (checkStub) checkStub(c, rmiConnectionImplStubClass);
+        try {
+            if (c.getClass() == rmiConnectionImplStubClass)
+                return shadowJrmpStub((RemoteObject) c);
+            logger.trace("getConnection",
+                    "Did not wrap " + c.getClass() + " to foil " +
+                    "stack search for classes: class loading semantics " +
+                    "may be incorrect");
+        } catch (Exception e) {
+            logger.error("getConnection",
+                    "Could not wrap " + c.getClass() + " to foil " +
+                    "stack search for classes: class loading semantics " +
+                    "may be incorrect: " + e);
+            logger.debug("getConnection",e);
+            // so just return the original stub, which will work for all
+            // but the most exotic class loading situations
+        }
+        return c;
+    }
+
+    private static byte[] base64ToByteArray(String s) {
+        int sLen = s.length();
+        int numGroups = sLen/4;
+        if (4*numGroups != sLen)
+            throw new IllegalArgumentException(
+                    "String length must be a multiple of four.");
+        int missingBytesInLastGroup = 0;
+        int numFullGroups = numGroups;
+        if (sLen != 0) {
+            if (s.charAt(sLen-1) == '=') {
+                missingBytesInLastGroup++;
+                numFullGroups--;
+            }
+            if (s.charAt(sLen-2) == '=')
+                missingBytesInLastGroup++;
+        }
+        byte[] result = new byte[3*numGroups - missingBytesInLastGroup];
+
+        // Translate all full groups from base64 to byte array elements
+        int inCursor = 0, outCursor = 0;
+        for (int i=0; i<numFullGroups; i++) {
+            int ch0 = base64toInt(s.charAt(inCursor++));
+            int ch1 = base64toInt(s.charAt(inCursor++));
+            int ch2 = base64toInt(s.charAt(inCursor++));
+            int ch3 = base64toInt(s.charAt(inCursor++));
+            result[outCursor++] = (byte) ((ch0 << 2) | (ch1 >> 4));
+            result[outCursor++] = (byte) ((ch1 << 4) | (ch2 >> 2));
+            result[outCursor++] = (byte) ((ch2 << 6) | ch3);
+        }
+
+        // Translate partial group, if present
+        if (missingBytesInLastGroup != 0) {
+            int ch0 = base64toInt(s.charAt(inCursor++));
+            int ch1 = base64toInt(s.charAt(inCursor++));
+            result[outCursor++] = (byte) ((ch0 << 2) | (ch1 >> 4));
+
+            if (missingBytesInLastGroup == 1) {
+                int ch2 = base64toInt(s.charAt(inCursor++));
+                result[outCursor++] = (byte) ((ch1 << 4) | (ch2 >> 2));
+            }
+        }
+        // assert inCursor == s.length()-missingBytesInLastGroup;
+        // assert outCursor == result.length;
+        return result;
+    }
+
+    /**
+     * Translates the specified character, which is assumed to be in the
+     * "Base 64 Alphabet" into its equivalent 6-bit positive integer.
+     *
+     * @throws IllegalArgumentException if
+     *        c is not in the Base64 Alphabet.
+     */
+    private static int base64toInt(char c) {
+        int result;
+
+        if (c >= base64ToInt.length)
+            result = -1;
+        else
+            result = base64ToInt[c];
+
+        if (result < 0)
+            throw new IllegalArgumentException("Illegal character " + c);
+        return result;
+    }
+
+    /**
+     * This array is a lookup table that translates unicode characters
+     * drawn from the "Base64 Alphabet" (as specified in Table 1 of RFC 2045)
+     * into their 6-bit positive integer equivalents.  Characters that
+     * are not in the Base64 alphabet but fall within the bounds of the
+     * array are translated to -1.
+     */
+    private static final byte base64ToInt[] = {
+        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+        -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54,
+        55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4,
+        5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
+        24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34,
+        35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
+    };
+
+    //--------------------------------------------------------------------
+    // Private stuff - Find / Set default class loader
+    //--------------------------------------------------------------------
+    private ClassLoader pushDefaultClassLoader() {
+        final Thread t = Thread.currentThread();
+        final ClassLoader old =  t.getContextClassLoader();
+        if (defaultClassLoader != null)
+            AccessController.doPrivileged(new PrivilegedAction<Void>() {
+                public Void run() {
+                    t.setContextClassLoader(defaultClassLoader);
+                    return null;
+                }
+            });
+            return old;
+    }
+
+    private void popDefaultClassLoader(final ClassLoader old) {
+        AccessController.doPrivileged(new PrivilegedAction<Void>() {
+            public Void run() {
+                Thread.currentThread().setContextClassLoader(old);
+                return null;
+            }
+        });
+    }
+
+    //--------------------------------------------------------------------
+    // Private variables
+    //--------------------------------------------------------------------
+    /**
+     * @serial The RMIServer stub of the RMI JMX Connector server to
+     * which this client connector is (or will be) connected. This
+     * field can be null when <var>jmxServiceURL</var> is not
+     * null. This includes the case where <var>jmxServiceURL</var>
+     * contains a serialized RMIServer stub. If both
+     * <var>rmiServer</var> and <var>jmxServiceURL</var> are null then
+     * serialization will fail.
+     *
+     * @see #RMIConnector(RMIServer,Map)
+     **/
+    private final RMIServer rmiServer;
+
+    /**
+     * @serial The JMXServiceURL of the RMI JMX Connector server to
+     * which this client connector will be connected. This field can
+     * be null when <var>rmiServer</var> is not null. If both
+     * <var>rmiServer</var> and <var>jmxServiceURL</var> are null then
+     * serialization will fail.
+     *
+     * @see #RMIConnector(JMXServiceURL,Map)
+     **/
+    private final JMXServiceURL jmxServiceURL;
+
+    // ---------------------------------------------------------
+    // WARNING - WARNING - WARNING - WARNING - WARNING - WARNING
+    // ---------------------------------------------------------
+    // Any transient variable which needs to be initialized should
+    // be initialized in the method initTransient()
+    private transient Map<String, Object> env;
+    private transient ClassLoader defaultClassLoader;
+    private transient RMIConnection connection;
+    private transient String connectionId;
+
+    private transient long clientNotifSeqNo = 0;
+
+    private transient WeakHashMap<Subject, WeakReference<MBeanServerConnection>> rmbscMap;
+    private transient WeakReference<MBeanServerConnection> nullSubjectConnRef = null;
+
+    private transient RMINotifClient rmiNotifClient;
+    // = new RMINotifClient(new Integer(0));
+
+    private transient long clientNotifCounter = 0;
+
+    private transient boolean connected;
+    // = false;
+    private transient boolean terminated;
+    // = false;
+
+    private transient Exception closeException;
+
+    private transient NotificationBroadcasterSupport connectionBroadcaster;
+
+    private transient ClientCommunicatorAdmin communicatorAdmin;
+
+    /**
+     * A static WeakReference to an {@link org.omg.CORBA.ORB ORB} to
+     * connect unconnected stubs.
+     **/
+    private static volatile WeakReference<Object> orb = null;
+
+    // TRACES & DEBUG
+    //---------------
+    private static String objects(final Object[] objs) {
+        if (objs == null)
+            return "null";
+        else
+            return Arrays.asList(objs).toString();
+    }
+
+    private static String strings(final String[] strs) {
+        return objects(strs);
+    }
+
+    static String getAttributesNames(AttributeList attributes) {
+        return attributes != null ?
+                attributes.asList().stream()
+                        .map(Attribute::getName)
+                        .collect(Collectors.joining(", ", "[", "]"))
+                : "[]";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.management.rmi/share/classes/javax/management/remote/rmi/RMIConnectorServer.java	Thu Feb 02 16:50:46 2017 +0000
@@ -0,0 +1,819 @@
+/*
+ * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package javax.management.remote.rmi;
+
+
+import com.sun.jmx.remote.security.MBeanServerFileAccessController;
+import com.sun.jmx.remote.util.ClassLogger;
+import com.sun.jmx.remote.util.EnvHelp;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectOutputStream;
+import java.net.MalformedURLException;
+import java.rmi.server.RMIClientSocketFactory;
+import java.rmi.server.RMIServerSocketFactory;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.Set;
+
+import javax.management.InstanceNotFoundException;
+import javax.management.MBeanServer;
+import javax.management.remote.JMXAuthenticator;
+
+import javax.management.remote.JMXConnectionNotification;
+import javax.management.remote.JMXConnector;
+import javax.management.remote.JMXConnectorServer;
+import javax.management.remote.JMXServiceURL;
+import javax.management.remote.MBeanServerForwarder;
+
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+
+/**
+ * <p>A JMX API connector server that creates RMI-based connections
+ * from remote clients.  Usually, such connector servers are made
+ * using {@link javax.management.remote.JMXConnectorServerFactory
+ * JMXConnectorServerFactory}.  However, specialized applications can
+ * use this class directly, for example with an {@link RMIServerImpl}
+ * object.</p>
+ *
+ * @since 1.5
+ */
+public class RMIConnectorServer extends JMXConnectorServer {
+    /**
+     * <p>Name of the attribute that specifies whether the {@link
+     * RMIServer} stub that represents an RMI connector server should
+     * override an existing stub at the same address.  The value
+     * associated with this attribute, if any, should be a string that
+     * is equal, ignoring case, to <code>"true"</code> or
+     * <code>"false"</code>.  The default value is false.</p>
+     */
+    public static final String JNDI_REBIND_ATTRIBUTE =
+        "jmx.remote.jndi.rebind";
+
+    /**
+     * <p>Name of the attribute that specifies the {@link
+     * RMIClientSocketFactory} for the RMI objects created in
+     * conjunction with this connector. The value associated with this
+     * attribute must be of type <code>RMIClientSocketFactory</code> and can
+     * only be specified in the <code>Map</code> argument supplied when
+     * creating a connector server.</p>
+     */
+    public static final String RMI_CLIENT_SOCKET_FACTORY_ATTRIBUTE =
+        "jmx.remote.rmi.client.socket.factory";
+
+    /**
+     * <p>Name of the attribute that specifies the {@link
+     * RMIServerSocketFactory} for the RMI objects created in
+     * conjunction with this connector. The value associated with this
+     * attribute must be of type <code>RMIServerSocketFactory</code> and can
+     * only be specified in the <code>Map</code> argument supplied when
+     * creating a connector server.</p>
+     */
+    public static final String RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE =
+        "jmx.remote.rmi.server.socket.factory";
+
+    /**
+    * Name of the attribute that specifies a list of class names acceptable
+    * as parameters to the {@link RMIServer#newClient(java.lang.Object) RMIServer.newClient()}
+    * remote method call.
+    * <p>
+    * This list of classes should correspond to the transitive closure of the
+    * credentials class (or classes) used by the installed {@linkplain JMXAuthenticator}
+    * associated with the {@linkplain RMIServer} implementation.
+    * <p>
+    * If the attribute is not set, or is null, then any class is
+    * deemed acceptable.
+    */
+    public static final String CREDENTIAL_TYPES =
+            "jmx.remote.rmi.server.credential.types";
+
+    /**
+     * <p>Makes an <code>RMIConnectorServer</code>.
+     * This is equivalent to calling {@link #RMIConnectorServer(
+     * JMXServiceURL,Map,RMIServerImpl,MBeanServer)
+     * RMIConnectorServer(directoryURL,environment,null,null)}</p>
+     *
+     * @param url the URL defining how to create the connector server.
+     * Cannot be null.
+     *
+     * @param environment attributes governing the creation and
+     * storing of the RMI object.  Can be null, which is equivalent to
+     * an empty Map.
+     *
+     * @exception IllegalArgumentException if <code>url</code> is null.
+     *
+     * @exception MalformedURLException if <code>url</code> does not
+     * conform to the syntax for an RMI connector, or if its protocol
+     * is not recognized by this implementation. Only "rmi" is valid when
+     * this constructor is used.
+     *
+     * @exception IOException if the connector server cannot be created
+     * for some reason or if it is inevitable that its {@link #start()
+     * start} method will fail.
+     */
+    public RMIConnectorServer(JMXServiceURL url, Map<String,?> environment)
+            throws IOException {
+        this(url, environment, (MBeanServer) null);
+    }
+
+    /**
+     * <p>Makes an <code>RMIConnectorServer</code> for the given MBean
+     * server.
+     * This is equivalent to calling {@link #RMIConnectorServer(
+     * JMXServiceURL,Map,RMIServerImpl,MBeanServer)
+     * RMIConnectorServer(directoryURL,environment,null,mbeanServer)}</p>
+     *
+     * @param url the URL defining how to create the connector server.
+     * Cannot be null.
+     *
+     * @param environment attributes governing the creation and
+     * storing of the RMI object.  Can be null, which is equivalent to
+     * an empty Map.
+     *
+     * @param mbeanServer the MBean server to which the new connector
+     * server is attached, or null if it will be attached by being
+     * registered as an MBean in the MBean server.
+     *
+     * @exception IllegalArgumentException if <code>url</code> is null.
+     *
+     * @exception MalformedURLException if <code>url</code> does not
+     * conform to the syntax for an RMI connector, or if its protocol
+     * is not recognized by this implementation. Only "rmi" is valid
+     * when this constructor is used.
+     *
+     * @exception IOException if the connector server cannot be created
+     * for some reason or if it is inevitable that its {@link #start()
+     * start} method will fail.
+     */
+    public RMIConnectorServer(JMXServiceURL url, Map<String,?> environment,
+                              MBeanServer mbeanServer)
+            throws IOException {
+        this(url, environment, (RMIServerImpl) null, mbeanServer);
+    }
+
+    /**
+     * <p>Makes an <code>RMIConnectorServer</code> for the given MBean
+     * server.</p>
+     *
+     * @param url the URL defining how to create the connector server.
+     * Cannot be null.
+     *
+     * @param environment attributes governing the creation and
+     * storing of the RMI object.  Can be null, which is equivalent to
+     * an empty Map.
+     *
+     * @param rmiServerImpl An implementation of the RMIServer interface,
+     *  consistent with the protocol type specified in <var>url</var>.
+     *  If this parameter is non null, the protocol type specified by
+     *  <var>url</var> is not constrained, and is assumed to be valid.
+     *  Otherwise, only "rmi" will be recognized.
+     *
+     * @param mbeanServer the MBean server to which the new connector
+     * server is attached, or null if it will be attached by being
+     * registered as an MBean in the MBean server.
+     *
+     * @exception IllegalArgumentException if <code>url</code> is null.
+     *
+     * @exception MalformedURLException if <code>url</code> does not
+     * conform to the syntax for an RMI connector, or if its protocol
+     * is not recognized by this implementation. Only "rmi" is recognized
+     * when <var>rmiServerImpl</var> is null.
+     *
+     * @exception IOException if the connector server cannot be created
+     * for some reason or if it is inevitable that its {@link #start()
+     * start} method will fail.
+     *
+     * @see #start
+     */
+    public RMIConnectorServer(JMXServiceURL url, Map<String,?> environment,
+                              RMIServerImpl rmiServerImpl,
+                              MBeanServer mbeanServer)
+            throws IOException {
+        super(mbeanServer);
+
+        if (url == null) throw new
+            IllegalArgumentException("Null JMXServiceURL");
+        if (rmiServerImpl == null) {
+            final String prt = url.getProtocol();
+            if (prt == null || !(prt.equals("rmi"))) {
+                final String msg = "Invalid protocol type: " + prt;
+                throw new MalformedURLException(msg);
+            }
+            final String urlPath = url.getURLPath();
+            if (!urlPath.equals("")
+                && !urlPath.equals("/")
+                && !urlPath.startsWith("/jndi/")) {
+                final String msg = "URL path must be empty or start with " +
+                    "/jndi/";
+                throw new MalformedURLException(msg);
+            }
+        }
+
+        if (environment == null)
+            this.attributes = Collections.emptyMap();
+        else {
+            EnvHelp.checkAttributes(environment);
+            this.attributes = Collections.unmodifiableMap(environment);
+        }
+
+        this.address = url;
+        this.rmiServerImpl = rmiServerImpl;
+    }
+
+    /**
+     * <p>Returns a client stub for this connector server.  A client
+     * stub is a serializable object whose {@link
+     * JMXConnector#connect(Map) connect} method can be used to make
+     * one new connection to this connector server.</p>
+     *
+     * @param env client connection parameters of the same sort that
+     * could be provided to {@link JMXConnector#connect(Map)
+     * JMXConnector.connect(Map)}.  Can be null, which is equivalent
+     * to an empty map.
+     *
+     * @return a client stub that can be used to make a new connection
+     * to this connector server.
+     *
+     * @exception UnsupportedOperationException if this connector
+     * server does not support the generation of client stubs.
+     *
+     * @exception IllegalStateException if the JMXConnectorServer is
+     * not started (see {@link #isActive()}).
+     *
+     * @exception IOException if a communications problem means that a
+     * stub cannot be created.
+     **/
+    public JMXConnector toJMXConnector(Map<String,?> env) throws IOException {
+        // The serialized for of rmiServerImpl is automatically
+        // a RMI server stub.
+        if (!isActive()) throw new
+            IllegalStateException("Connector is not active");
+
+        // Merge maps
+        Map<String, Object> usemap = new HashMap<String, Object>(
+                (this.attributes==null)?Collections.<String, Object>emptyMap():
+                    this.attributes);
+
+        if (env != null) {
+            EnvHelp.checkAttributes(env);
+            usemap.putAll(env);
+        }
+
+        usemap = EnvHelp.filterAttributes(usemap);
+
+        final RMIServer stub=(RMIServer)rmiServerImpl.toStub();
+
+        return new RMIConnector(stub, usemap);
+    }
+
+    /**
+     * <p>Activates the connector server, that is starts listening for
+     * client connections.  Calling this method when the connector
+     * server is already active has no effect.  Calling this method
+     * when the connector server has been stopped will generate an
+     * <code>IOException</code>.</p>
+     *
+     * <p>The behavior of this method when called for the first time
+     * depends on the parameters that were supplied at construction,
+     * as described below.</p>
+     *
+     * <p>First, an object of a subclass of {@link RMIServerImpl} is
+     * required, to export the connector server through RMI:</p>
+     *
+     * <ul>
+     *
+     * <li>If an <code>RMIServerImpl</code> was supplied to the
+     * constructor, it is used.
+     *
+     * <li>Otherwise, if the <code>JMXServiceURL</code>
+     * was null, or its protocol part was <code>rmi</code>, an object
+     * of type {@link RMIJRMPServerImpl} is created.
+     *
+     * <li>Otherwise, the implementation can create an
+     * implementation-specific {@link RMIServerImpl} or it can throw
+     * {@link MalformedURLException}.
+     *
+     * </ul>
+     *
+     * <p>If the given address includes a JNDI directory URL as
+     * specified in the package documentation for {@link
+     * javax.management.remote.rmi}, then this
+     * <code>RMIConnectorServer</code> will bootstrap by binding the
+     * <code>RMIServerImpl</code> to the given address.</p>
+     *
+     * <p>If the URL path part of the <code>JMXServiceURL</code> was
+     * empty or a single slash (<code>/</code>), then the RMI object
+     * will not be bound to a directory.  Instead, a reference to it
+     * will be encoded in the URL path of the RMIConnectorServer
+     * address (returned by {@link #getAddress()}).  The encodings for
+     * <code>rmi</code> are described in the package documentation for
+     * {@link javax.management.remote.rmi}.</p>
+     *
+     * <p>The behavior when the URL path is neither empty nor a JNDI
+     * directory URL, or when the protocol is not <code>rmi</code>,
+     * is implementation defined, and may include throwing
+     * {@link MalformedURLException} when the connector server is created
+     * or when it is started.</p>
+     *
+     * @exception IllegalStateException if the connector server has
+     * not been attached to an MBean server.
+     * @exception IOException if the connector server cannot be
+     * started.
+     */
+    public synchronized void start() throws IOException {
+        final boolean tracing = logger.traceOn();
+
+        if (state == STARTED) {
+            if (tracing) logger.trace("start", "already started");
+            return;
+        } else if (state == STOPPED) {
+            if (tracing) logger.trace("start", "already stopped");
+            throw new IOException("The server has been stopped.");
+        }
+
+        if (getMBeanServer() == null)
+            throw new IllegalStateException("This connector server is not " +
+                                            "attached to an MBean server");
+
+        // Check the internal access file property to see
+        // if an MBeanServerForwarder is to be provided
+        //
+        if (attributes != null) {
+            // Check if access file property is specified
+            //
+            String accessFile =
+                (String) attributes.get("jmx.remote.x.access.file");
+            if (accessFile != null) {
+                // Access file property specified, create an instance
+                // of the MBeanServerFileAccessController class
+                //
+                MBeanServerForwarder mbsf;
+                try {
+                    mbsf = new MBeanServerFileAccessController(accessFile);
+                } catch (IOException e) {
+                    throw EnvHelp.initCause(
+                        new IllegalArgumentException(e.getMessage()), e);
+                }
+                // Set the MBeanServerForwarder
+                //
+                setMBeanServerForwarder(mbsf);
+            }
+        }
+
+        try {
+            if (tracing) logger.trace("start", "setting default class loader");
+            defaultClassLoader = EnvHelp.resolveServerClassLoader(
+                    attributes, getMBeanServer());
+        } catch (InstanceNotFoundException infc) {
+            IllegalArgumentException x = new
+                IllegalArgumentException("ClassLoader not found: "+infc);
+            throw EnvHelp.initCause(x,infc);
+        }
+
+        if (tracing) logger.trace("start", "setting RMIServer object");
+        final RMIServerImpl rmiServer;
+
+        if (rmiServerImpl != null)
+            rmiServer = rmiServerImpl;
+        else
+            rmiServer = newServer();
+
+        rmiServer.setMBeanServer(getMBeanServer());
+        rmiServer.setDefaultClassLoader(defaultClassLoader);
+        rmiServer.setRMIConnectorServer(this);
+        rmiServer.export();
+
+        try {
+            if (tracing) logger.trace("start", "getting RMIServer object to export");
+            final RMIServer objref = objectToBind(rmiServer, attributes);
+
+            if (address != null && address.getURLPath().startsWith("/jndi/")) {
+                final String jndiUrl = address.getURLPath().substring(6);
+
+                if (tracing)
+                    logger.trace("start", "Using external directory: " + jndiUrl);
+
+                String stringBoolean = (String) attributes.get(JNDI_REBIND_ATTRIBUTE);
+                final boolean rebind = EnvHelp.computeBooleanFromString( stringBoolean );
+
+                if (tracing)
+                    logger.trace("start", JNDI_REBIND_ATTRIBUTE + "=" + rebind);
+
+                try {
+                    if (tracing) logger.trace("start", "binding to " + jndiUrl);
+
+                    final Hashtable<?, ?> usemap = EnvHelp.mapToHashtable(attributes);
+
+                    bind(jndiUrl, usemap, objref, rebind);
+
+                    boundJndiUrl = jndiUrl;
+                } catch (NamingException e) {
+                    // fit e in the nested exception if we are on 1.4
+                    throw newIOException("Cannot bind to URL ["+jndiUrl+"]: "
+                                         + e, e);
+                }
+            } else {
+                // if jndiURL is null, we must encode the stub into the URL.
+                if (tracing) logger.trace("start", "Encoding URL");
+
+                encodeStubInAddress(objref, attributes);
+
+                if (tracing) logger.trace("start", "Encoded URL: " + this.address);
+            }
+        } catch (Exception e) {
+            try {
+                rmiServer.close();
+            } catch (Exception x) {
+                // OK: we are already throwing another exception
+            }
+            if (e instanceof RuntimeException)
+                throw (RuntimeException) e;
+            else if (e instanceof IOException)
+                throw (IOException) e;
+            else
+                throw newIOException("Got unexpected exception while " +
+                                     "starting the connector server: "
+                                     + e, e);
+        }
+
+        rmiServerImpl = rmiServer;
+
+        synchronized(openedServers) {
+            openedServers.add(this);
+        }
+
+        state = STARTED;
+
+        if (tracing) {
+            logger.trace("start", "Connector Server Address = " + address);
+            logger.trace("start", "started.");
+        }
+    }
+
+    /**
+     * <p>Deactivates the connector server, that is, stops listening for
+     * client connections.  Calling this method will also close all
+     * client connections that were made by this server.  After this
+     * method returns, whether normally or with an exception, the
+     * connector server will not create any new client
+     * connections.</p>
+     *
+     * <p>Once a connector server has been stopped, it cannot be started
+     * again.</p>
+     *
+     * <p>Calling this method when the connector server has already
+     * been stopped has no effect.  Calling this method when the
+     * connector server has not yet been started will disable the
+     * connector server object permanently.</p>
+     *
+     * <p>If closing a client connection produces an exception, that
+     * exception is not thrown from this method.  A {@link
+     * JMXConnectionNotification} is emitted from this MBean with the
+     * connection ID of the connection that could not be closed.</p>
+     *
+     * <p>Closing a connector server is a potentially slow operation.
+     * For example, if a client machine with an open connection has
+     * crashed, the close operation might have to wait for a network
+     * protocol timeout.  Callers that do not want to block in a close
+     * operation should do it in a separate thread.</p>
+     *
+     * <p>This method calls the method {@link RMIServerImpl#close()
+     * close} on the connector server's <code>RMIServerImpl</code>
+     * object.</p>
+     *
+     * <p>If the <code>RMIServerImpl</code> was bound to a JNDI
+     * directory by the {@link #start() start} method, it is unbound
+     * from the directory by this method.</p>
+     *
+     * @exception IOException if the server cannot be closed cleanly,
+     * or if the <code>RMIServerImpl</code> cannot be unbound from the
+     * directory.  When this exception is thrown, the server has
+     * already attempted to close all client connections, if
+     * appropriate; to call {@link RMIServerImpl#close()}; and to
+     * unbind the <code>RMIServerImpl</code> from its directory, if
+     * appropriate.  All client connections are closed except possibly
+     * those that generated exceptions when the server attempted to
+     * close them.
+     */
+    public void stop() throws IOException {
+        final boolean tracing = logger.traceOn();
+
+        synchronized (this) {
+            if (state == STOPPED) {
+                if (tracing) logger.trace("stop","already stopped.");
+                return;
+            } else if (state == CREATED) {
+                if (tracing) logger.trace("stop","not started yet.");
+            }
+
+            if (tracing) logger.trace("stop", "stopping.");
+            state = STOPPED;
+        }
+
+        synchronized(openedServers) {
+            openedServers.remove(this);
+        }
+
+        IOException exception = null;
+
+        // rmiServerImpl can be null if stop() called without start()
+        if (rmiServerImpl != null) {
+            try {
+                if (tracing) logger.trace("stop", "closing RMI server.");
+                rmiServerImpl.close();
+            } catch (IOException e) {
+                if (tracing) logger.trace("stop", "failed to close RMI server: " + e);
+                if (logger.debugOn()) logger.debug("stop",e);
+                exception = e;
+            }
+        }
+
+        if (boundJndiUrl != null) {
+            try {
+                if (tracing)
+                    logger.trace("stop",
+                          "unbind from external directory: " + boundJndiUrl);
+
+                final Hashtable<?, ?> usemap = EnvHelp.mapToHashtable(attributes);
+
+                InitialContext ctx =
+                    new InitialContext(usemap);
+
+                ctx.unbind(boundJndiUrl);
+
+                ctx.close();
+            } catch (NamingException e) {
+                if (tracing) logger.trace("stop", "failed to unbind RMI server: "+e);
+                if (logger.debugOn()) logger.debug("stop",e);
+                // fit e in as the nested exception if we are on 1.4
+                if (exception == null)
+                    exception = newIOException("Cannot bind to URL: " + e, e);
+            }
+        }
+
+        if (exception != null) throw exception;
+
+        if (tracing) logger.trace("stop", "stopped");
+    }
+
+    public synchronized boolean isActive() {
+        return (state == STARTED);
+    }
+
+    public JMXServiceURL getAddress() {
+        if (!isActive())
+            return null;
+        return address;
+    }
+
+    public Map<String,?> getAttributes() {
+        Map<String, ?> map = EnvHelp.filterAttributes(attributes);
+        return Collections.unmodifiableMap(map);
+    }
+
+    @Override
+    public synchronized
+        void setMBeanServerForwarder(MBeanServerForwarder mbsf) {
+        super.setMBeanServerForwarder(mbsf);
+        if (rmiServerImpl != null)
+            rmiServerImpl.setMBeanServer(getMBeanServer());
+    }
+
+    /* We repeat the definitions of connection{Opened,Closed,Failed}
+       here so that they are accessible to other classes in this package
+       even though they have protected access.  */
+
+    @Override
+    protected void connectionOpened(String connectionId, String message,
+                                    Object userData) {
+        super.connectionOpened(connectionId, message, userData);
+    }
+
+    @Override
+    protected void connectionClosed(String connectionId, String message,
+                                    Object userData) {
+        super.connectionClosed(connectionId, message, userData);
+    }
+
+    @Override
+    protected void connectionFailed(String connectionId, String message,
+                                    Object userData) {
+        super.connectionFailed(connectionId, message, userData);
+    }
+
+    /**
+     * Bind a stub to a registry.
+     * @param jndiUrl URL of the stub in the registry, extracted
+     *        from the <code>JMXServiceURL</code>.
+     * @param attributes A Hashtable containing environment parameters,
+     *        built from the Map specified at this object creation.
+     * @param rmiServer The object to bind in the registry
+     * @param rebind true if the object must be rebound.
+     **/
+    void bind(String jndiUrl, Hashtable<?, ?> attributes,
+              RMIServer rmiServer, boolean rebind)
+        throws NamingException, MalformedURLException {
+        // if jndiURL is not null, we nust bind the stub to a
+        // directory.
+        InitialContext ctx =
+            new InitialContext(attributes);
+
+        if (rebind)
+            ctx.rebind(jndiUrl, rmiServer);
+        else
+            ctx.bind(jndiUrl, rmiServer);
+        ctx.close();
+    }
+
+    /**
+     * Creates a new RMIServerImpl.
+     **/
+    RMIServerImpl newServer() throws IOException {
+        final int port;
+        if (address == null)
+            port = 0;
+        else
+            port = address.getPort();
+
+        return newJRMPServer(attributes, port);
+    }
+
+    /**
+     * Encode a stub into the JMXServiceURL.
+     * @param rmiServer The stub object to encode in the URL
+     * @param attributes A Map containing environment parameters,
+     *        built from the Map specified at this object creation.
+     **/
+    private void encodeStubInAddress(
+            RMIServer rmiServer, Map<String, ?> attributes)
+            throws IOException {
+
+        final String protocol, host;
+        final int port;
+
+        if (address == null) {
+            protocol = "rmi";
+            host = null; // will default to local host name
+            port = 0;
+        } else {
+            protocol = address.getProtocol();
+            host = (address.getHost().equals("")) ? null : address.getHost();
+            port = address.getPort();
+        }
+
+        final String urlPath = encodeStub(rmiServer, attributes);
+
+        address = new JMXServiceURL(protocol, host, port, urlPath);
+    }
+
+    /**
+     * Returns the IOR of the given rmiServer.
+     **/
+    static String encodeStub(
+            RMIServer rmiServer, Map<String, ?> env) throws IOException {
+        return "/stub/" + encodeJRMPStub(rmiServer, env);
+    }
+
+    static String encodeJRMPStub(
+            RMIServer rmiServer, Map<String, ?> env)
+            throws IOException {
+        ByteArrayOutputStream bout = new ByteArrayOutputStream();
+        ObjectOutputStream oout = new ObjectOutputStream(bout);
+        oout.writeObject(rmiServer);
+        oout.close();
+        byte[] bytes = bout.toByteArray();
+        return byteArrayToBase64(bytes);
+    }
+
+    /**
+     * Object that we will bind to the registry.
+     * This object is a stub connected to our RMIServerImpl.
+     **/
+    private static RMIServer objectToBind(
+            RMIServerImpl rmiServer, Map<String, ?> env)
+        throws IOException {
+        return (RMIServer)rmiServer.toStub();
+    }
+
+    private static RMIServerImpl newJRMPServer(Map<String, ?> env, int port)
+            throws IOException {
+        RMIClientSocketFactory csf = (RMIClientSocketFactory)
+            env.get(RMI_CLIENT_SOCKET_FACTORY_ATTRIBUTE);
+        RMIServerSocketFactory ssf = (RMIServerSocketFactory)
+            env.get(RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE);
+        return new RMIJRMPServerImpl(port, csf, ssf, env);
+    }
+
+    private static String byteArrayToBase64(byte[] a) {
+        int aLen = a.length;
+        int numFullGroups = aLen/3;
+        int numBytesInPartialGroup = aLen - 3*numFullGroups;
+        int resultLen = 4*((aLen + 2)/3);
+        final StringBuilder result = new StringBuilder(resultLen);
+
+        // Translate all full groups from byte array elements to Base64
+        int inCursor = 0;
+        for (int i=0; i<numFullGroups; i++) {
+            int byte0 = a[inCursor++] & 0xff;
+            int byte1 = a[inCursor++] & 0xff;
+            int byte2 = a[inCursor++] & 0xff;
+            result.append(intToAlpha[byte0 >> 2]);
+            result.append(intToAlpha[(byte0 << 4)&0x3f | (byte1 >> 4)]);
+            result.append(intToAlpha[(byte1 << 2)&0x3f | (byte2 >> 6)]);
+            result.append(intToAlpha[byte2 & 0x3f]);
+        }
+
+        // Translate partial group if present
+        if (numBytesInPartialGroup != 0) {
+            int byte0 = a[inCursor++] & 0xff;
+            result.append(intToAlpha[byte0 >> 2]);
+            if (numBytesInPartialGroup == 1) {
+                result.append(intToAlpha[(byte0 << 4) & 0x3f]);
+                result.append("==");
+            } else {
+                // assert numBytesInPartialGroup == 2;
+                int byte1 = a[inCursor++] & 0xff;
+                result.append(intToAlpha[(byte0 << 4)&0x3f | (byte1 >> 4)]);
+                result.append(intToAlpha[(byte1 << 2)&0x3f]);
+                result.append('=');
+            }
+        }
+        // assert inCursor == a.length;
+        // assert result.length() == resultLen;
+        return result.toString();
+    }
+
+    /**
+     * This array is a lookup table that translates 6-bit positive integer
+     * index values into their "Base64 Alphabet" equivalents as specified
+     * in Table 1 of RFC 2045.
+     */
+    private static final char intToAlpha[] = {
+        'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
+        'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
+        'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
+        'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
+        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
+    };
+
+    /**
+     * Construct a new IOException with a nested exception.
+     * The nested exception is set only if JDK {@literal >= 1.4}
+     */
+    private static IOException newIOException(String message,
+                                              Throwable cause) {
+        final IOException x = new IOException(message);
+        return EnvHelp.initCause(x,cause);
+    }
+
+
+    // Private variables
+    // -----------------
+
+    private static ClassLogger logger =
+        new ClassLogger("javax.management.remote.rmi", "RMIConnectorServer");
+
+    private JMXServiceURL address;
+    private RMIServerImpl rmiServerImpl;
+    private final Map<String, ?> attributes;
+    private ClassLoader defaultClassLoader = null;
+
+    private String boundJndiUrl;
+
+    // state
+    private static final int CREATED = 0;
+    private static final int STARTED = 1;
+    private static final int STOPPED = 2;
+
+    private int state = CREATED;
+    private final static Set<RMIConnectorServer> openedServers =
+            new HashSet<RMIConnectorServer>();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.management.rmi/share/classes/javax/management/remote/rmi/RMIIIOPServerImpl.java	Thu Feb 02 16:50:46 2017 +0000
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package javax.management.remote.rmi;
+
+import java.io.IOException;
+import java.rmi.Remote;
+import java.util.Map;
+import javax.security.auth.Subject;
+
+/**
+ * <p>An {@link RMIServerImpl} that is exported through IIOP and that
+ * creates client connections as RMI objects exported through IIOP.
+ * User code does not usually reference this class directly.</p>
+ *
+ * @see RMIServerImpl
+ *
+ * @since 1.5
+ * @deprecated This transport is no longer supported.
+ */
+@Deprecated
+public class RMIIIOPServerImpl extends RMIServerImpl {
+    /**
+     * Throws {@linkplain UnsupportedOperationException}
+     *
+     * @param env the environment containing attributes for the new
+     * <code>RMIServerImpl</code>.  Can be null, which is equivalent
+     * to an empty Map.
+     *
+     * @throws IOException if the RMI object cannot be created.
+     */
+    public RMIIIOPServerImpl(Map<String,?> env)
+            throws IOException {
+        super(env);
+
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    protected void export() throws IOException {
+        throw new UnsupportedOperationException("Method not supported. JMX RMI-IIOP is deprecated");
+    }
+
+    @Override
+    protected String getProtocol() {
+        return "iiop";
+    }
+
+    @Override
+    public Remote toStub() throws IOException {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    protected RMIConnection makeClient(String connectionId, Subject subject)
+            throws IOException {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    protected void closeClient(RMIConnection client) throws IOException {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    protected void closeServer() throws IOException {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    RMIConnection doNewClient(final Object credentials) throws IOException {
+        throw new UnsupportedOperationException();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.management.rmi/share/classes/javax/management/remote/rmi/RMIJRMPServerImpl.java	Thu Feb 02 16:50:46 2017 +0000
@@ -0,0 +1,279 @@
+/*
+ * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package javax.management.remote.rmi;
+
+import java.io.IOException;
+import java.rmi.NoSuchObjectException;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.rmi.server.RMIClientSocketFactory;
+import java.rmi.server.RMIServerSocketFactory;
+import java.rmi.server.UnicastRemoteObject;
+import java.rmi.server.RemoteObject;
+import java.util.Map;
+import java.util.Collections;
+import javax.security.auth.Subject;
+
+import com.sun.jmx.remote.internal.rmi.RMIExporter;
+import com.sun.jmx.remote.util.EnvHelp;
+import java.io.ObjectStreamClass;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import sun.reflect.misc.ReflectUtil;
+import sun.rmi.server.DeserializationChecker;
+import sun.rmi.server.UnicastServerRef;
+import sun.rmi.server.UnicastServerRef2;
+
+/**
+ * <p>An {@link RMIServer} object that is exported through JRMP and that
+ * creates client connections as RMI objects exported through JRMP.
+ * User code does not usually reference this class directly.</p>
+ *
+ * @see RMIServerImpl
+ *
+ * @since 1.5
+ */
+public class RMIJRMPServerImpl extends RMIServerImpl {
+
+    private final ExportedWrapper exportedWrapper;
+
+    /**
+     * <p>Creates a new {@link RMIServer} object that will be exported
+     * on the given port using the given socket factories.</p>
+     *
+     * @param port the port on which this object and the {@link
+     * RMIConnectionImpl} objects it creates will be exported.  Can be
+     * zero, to indicate any available port.
+     *
+     * @param csf the client socket factory for the created RMI
+     * objects.  Can be null.
+     *
+     * @param ssf the server socket factory for the created RMI
+     * objects.  Can be null.
+     *
+     * @param env the environment map.  Can be null.
+     *
+     * @exception IOException if the {@link RMIServer} object
+     * cannot be created.
+     *
+     * @exception IllegalArgumentException if <code>port</code> is
+     * negative.
+     */
+    public RMIJRMPServerImpl(int port,
+                             RMIClientSocketFactory csf,
+                             RMIServerSocketFactory ssf,
+                             Map<String,?> env)
+            throws IOException {
+
+        super(env);
+
+        if (port < 0)
+            throw new IllegalArgumentException("Negative port: " + port);
+
+        this.port = port;
+        this.csf = csf;
+        this.ssf = ssf;
+        this.env = (env == null) ? Collections.<String, Object>emptyMap() : env;
+
+        String[] credentialsTypes
+                = (String[]) this.env.get(RMIConnectorServer.CREDENTIAL_TYPES);
+        List<String> types = null;
+        if (credentialsTypes != null) {
+            types = new ArrayList<>();
+            for (String type : credentialsTypes) {
+                if (type == null) {
+                    throw new IllegalArgumentException("A credential type is null.");
+                }
+                ReflectUtil.checkPackageAccess(type);
+                types.add(type);
+            }
+        }
+        exportedWrapper = types != null ?
+                new ExportedWrapper(this, types) :
+                null;
+    }
+
+    protected void export() throws IOException {
+        if (exportedWrapper != null) {
+            export(exportedWrapper);
+        } else {
+            export(this);
+        }
+    }
+
+    private void export(Remote obj) throws RemoteException {
+        final RMIExporter exporter =
+            (RMIExporter) env.get(RMIExporter.EXPORTER_ATTRIBUTE);
+        final boolean daemon = EnvHelp.isServerDaemon(env);
+
+        if (daemon && exporter != null) {
+            throw new IllegalArgumentException("If "+EnvHelp.JMX_SERVER_DAEMON+
+                    " is specified as true, "+RMIExporter.EXPORTER_ATTRIBUTE+
+                    " cannot be used to specify an exporter!");
+        }
+
+        if (daemon) {
+            if (csf == null && ssf == null) {
+                new UnicastServerRef(port).exportObject(obj, null, true);
+            } else {
+                new UnicastServerRef2(port, csf, ssf).exportObject(obj, null, true);
+            }
+        } else if (exporter != null) {
+            exporter.exportObject(obj, port, csf, ssf);
+        } else {
+            UnicastRemoteObject.exportObject(obj, port, csf, ssf);
+        }
+    }
+
+    private void unexport(Remote obj, boolean force)
+            throws NoSuchObjectException {
+        RMIExporter exporter =
+            (RMIExporter) env.get(RMIExporter.EXPORTER_ATTRIBUTE);
+        if (exporter == null)
+            UnicastRemoteObject.unexportObject(obj, force);
+        else
+            exporter.unexportObject(obj, force);
+    }
+
+    protected String getProtocol() {
+        return "rmi";
+    }
+
+    /**
+     * <p>Returns a serializable stub for this {@link RMIServer} object.</p>
+     *
+     * @return a serializable stub.
+     *
+     * @exception IOException if the stub cannot be obtained - e.g the
+     *            RMIJRMPServerImpl has not been exported yet.
+     */
+    public Remote toStub() throws IOException {
+        if (exportedWrapper != null) {
+            return RemoteObject.toStub(exportedWrapper);
+        } else {
+            return RemoteObject.toStub(this);
+        }
+    }
+
+    /**
+     * <p>Creates a new client connection as an RMI object exported
+     * through JRMP. The port and socket factories for the new
+     * {@link RMIConnection} object are the ones supplied
+     * to the <code>RMIJRMPServerImpl</code> constructor.</p>
+     *
+     * @param connectionId the ID of the new connection. Every
+     * connection opened by this connector server will have a
+     * different id.  The behavior is unspecified if this parameter is
+     * null.
+     *
+     * @param subject the authenticated subject.  Can be null.
+     *
+     * @return the newly-created <code>RMIConnection</code>.
+     *
+     * @exception IOException if the new {@link RMIConnection}
+     * object cannot be created or exported.
+     */
+    protected RMIConnection makeClient(String connectionId, Subject subject)
+            throws IOException {
+
+        if (connectionId == null)
+            throw new NullPointerException("Null connectionId");
+
+        RMIConnection client =
+            new RMIConnectionImpl(this, connectionId, getDefaultClassLoader(),
+                                  subject, env);
+        export(client);
+        return client;
+    }
+
+    protected void closeClient(RMIConnection client) throws IOException {
+        unexport(client, true);
+    }
+
+    /**
+     * <p>Called by {@link #close()} to close the connector server by
+     * unexporting this object.  After returning from this method, the
+     * connector server must not accept any new connections.</p>
+     *
+     * @exception IOException if the attempt to close the connector
+     * server failed.
+     */
+    protected void closeServer() throws IOException {
+        if (exportedWrapper != null) {
+            unexport(exportedWrapper, true);
+        } else {
+            unexport(this, true);
+        }
+    }
+
+    private final int port;
+    private final RMIClientSocketFactory csf;
+    private final RMIServerSocketFactory ssf;
+    private final Map<String, ?> env;
+
+    private static class ExportedWrapper implements RMIServer, DeserializationChecker {
+        private final RMIServer impl;
+        private final List<String> allowedTypes;
+
+        private ExportedWrapper(RMIServer impl, List<String> credentialsTypes) {
+            this.impl = impl;
+            allowedTypes = credentialsTypes;
+        }
+
+        @Override
+        public String getVersion() throws RemoteException {
+            return impl.getVersion();
+        }
+
+        @Override
+        public RMIConnection newClient(Object credentials) throws IOException {
+            return impl.newClient(credentials);
+        }
+
+        @Override
+        public void check(Method method, ObjectStreamClass descriptor,
+                int paramIndex, int callID) {
+            String type = descriptor.getName();
+            if (!allowedTypes.contains(type)) {
+                throw new ClassCastException("Unsupported type: " + type);
+            }
+        }
+
+        @Override
+        public void checkProxyClass(Method method, String[] ifaces,
+                int paramIndex, int callID) {
+            if (ifaces != null && ifaces.length > 0) {
+                for (String iface : ifaces) {
+                    if (!allowedTypes.contains(iface)) {
+                        throw new ClassCastException("Unsupported type: " + iface);
+                    }
+                }
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.management.rmi/share/classes/javax/management/remote/rmi/RMIServer.java	Thu Feb 02 16:50:46 2017 +0000
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2002, 2007, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package javax.management.remote.rmi;
+
+import java.io.IOException;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+
+/**
+ * <p>RMI object used to establish connections to an RMI connector.
+ * There is one Remote object implementing this interface for each RMI
+ * connector.</p>
+ *
+ * <p>User code does not usually refer to this interface.  It is
+ * specified as part of the public API so that different
+ * implementations of that API will interoperate.</p>
+ *
+ * @since 1.5
+ */
+public interface RMIServer extends Remote {
+    /**
+     * <p>The version of the RMI Connector Protocol understood by this
+     * connector server.  This is a string with the following format:</p>
+     *
+     * <pre>
+     * <em>protocol-version</em> <em>implementation-name</em>
+     * </pre>
+     *
+     * <p>The <code><em>protocol-version</em></code> is a series of
+     * two or more non-negative integers separated by periods
+     * (<code>.</code>).  An implementation of the version described
+     * by this documentation must use the string <code>1.0</code>
+     * here.</p>
+     *
+     * <p>After the protocol version there must be a space, followed
+     * by the implementation name.  The format of the implementation
+     * name is unspecified.  It is recommended that it include an
+     * implementation version number.  An implementation can use an
+     * empty string as its implementation name, for example for
+     * security reasons.</p>
+     *
+     * @return a string with the format described here.
+     *
+     * @exception RemoteException if there is a communication
+     * exception during the remote method call.
+     */
+    public String getVersion() throws RemoteException;
+
+    /**
+     * <p>Makes a new connection through this RMI connector.  Each
+     * remote client calls this method to obtain a new RMI object
+     * representing its connection.</p>
+     *
+     * @param credentials this object specifies the user-defined credentials
+     * to be passed in to the server in order to authenticate the user before
+     * creating the <code>RMIConnection</code>.  Can be null.
+     *
+     * @return the newly-created connection object.
+     *
+     * @exception IOException if the new client object cannot be
+     * created or exported, or if there is a communication exception
+     * during the remote method call.
+     *
+     * @exception SecurityException if the given credentials do not
+     * allow the server to authenticate the caller successfully.
+     */
+    public RMIConnection newClient(Object credentials) throws IOException;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.management.rmi/share/classes/javax/management/remote/rmi/RMIServerImpl.java	Thu Feb 02 16:50:46 2017 +0000
@@ -0,0 +1,550 @@
+/*
+ * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package javax.management.remote.rmi;
+
+import com.sun.jmx.remote.internal.ArrayNotificationBuffer;
+import com.sun.jmx.remote.internal.NotificationBuffer;
+import com.sun.jmx.remote.security.JMXPluggableAuthenticator;
+import com.sun.jmx.remote.util.ClassLogger;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.lang.ref.WeakReference;
+import java.rmi.Remote;
+import java.rmi.server.RemoteServer;
+import java.rmi.server.ServerNotActiveException;
+import java.security.Principal;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.management.MBeanServer;
+import javax.management.remote.JMXAuthenticator;
+import javax.management.remote.JMXConnectorServer;
+import javax.security.auth.Subject;
+
+/**
+ * <p>An RMI object representing a connector server.  Remote clients
+ * can make connections using the {@link #newClient(Object)} method.  This
+ * method returns an RMI object representing the connection.</p>
+ *
+ * <p>User code does not usually reference this class directly.
+ * RMI connection servers are usually created with the class {@link
+ * RMIConnectorServer}.  Remote clients usually create connections
+ * either with {@link javax.management.remote.JMXConnectorFactory}
+ * or by instantiating {@link RMIConnector}.</p>
+ *
+ * <p>This is an abstract class.  Concrete subclasses define the
+ * details of the client connection objects.</p>
+ *
+ * @since 1.5
+ */
+public abstract class RMIServerImpl implements Closeable, RMIServer {
+    /**
+     * <p>Constructs a new <code>RMIServerImpl</code>.</p>
+     *
+     * @param env the environment containing attributes for the new
+     * <code>RMIServerImpl</code>.  Can be null, which is equivalent
+     * to an empty Map.
+     */
+    public RMIServerImpl(Map<String,?> env) {
+        this.env = (env == null) ? Collections.<String,Object>emptyMap() : env;
+    }
+
+    void setRMIConnectorServer(RMIConnectorServer connServer)
+            throws IOException {
+        this.connServer = connServer;
+    }
+
+    /**
+     * <p>Exports this RMI object.</p>
+     *
+     * @exception IOException if this RMI object cannot be exported.
+     */
+    protected abstract void export() throws IOException;
+
+    /**
+     * Returns a remotable stub for this server object.
+     * @return a remotable stub.
+     * @exception IOException if the stub cannot be obtained - e.g the
+     *            RMIServerImpl has not been exported yet.
+     **/
+    public abstract Remote toStub() throws IOException;
+
+    /**
+     * <p>Sets the default <code>ClassLoader</code> for this connector
+     * server. New client connections will use this classloader.
+     * Existing client connections are unaffected.</p>
+     *
+     * @param cl the new <code>ClassLoader</code> to be used by this
+     * connector server.
+     *
+     * @see #getDefaultClassLoader
+     */
+    public synchronized void setDefaultClassLoader(ClassLoader cl) {
+        this.cl = cl;
+    }
+
+    /**
+     * <p>Gets the default <code>ClassLoader</code> used by this connector
+     * server.</p>
+     *
+     * @return the default <code>ClassLoader</code> used by this
+     * connector server.
+     *
+     * @see #setDefaultClassLoader
+     */
+    public synchronized ClassLoader getDefaultClassLoader() {
+        return cl;
+    }
+
+    /**
+     * <p>Sets the <code>MBeanServer</code> to which this connector
+     * server is attached. New client connections will interact
+     * with this <code>MBeanServer</code>. Existing client connections are
+     * unaffected.</p>
+     *
+     * @param mbs the new <code>MBeanServer</code>.  Can be null, but
+     * new client connections will be refused as long as it is.
+     *
+     * @see #getMBeanServer
+     */
+    public synchronized void setMBeanServer(MBeanServer mbs) {
+        this.mbeanServer = mbs;
+    }
+
+    /**
+     * <p>The <code>MBeanServer</code> to which this connector server
+     * is attached.  This is the last value passed to {@link
+     * #setMBeanServer} on this object, or null if that method has
+     * never been called.</p>
+     *
+     * @return the <code>MBeanServer</code> to which this connector
+     * is attached.
+     *
+     * @see #setMBeanServer
+     */
+    public synchronized MBeanServer getMBeanServer() {
+        return mbeanServer;
+    }
+
+    public String getVersion() {
+        // Expected format is: "protocol-version implementation-name"
+        try {
+            return "1.0 java_runtime_" +
+                    System.getProperty("java.runtime.version");
+        } catch (SecurityException e) {
+            return "1.0 ";
+        }
+    }
+
+    /**
+     * <p>Creates a new client connection.  This method calls {@link
+     * #makeClient makeClient} and adds the returned client connection
+     * object to an internal list.  When this
+     * <code>RMIServerImpl</code> is shut down via its {@link
+     * #close()} method, the {@link RMIConnection#close() close()}
+     * method of each object remaining in the list is called.</p>
+     *
+     * <p>The fact that a client connection object is in this internal
+     * list does not prevent it from being garbage collected.</p>
+     *
+     * @param credentials this object specifies the user-defined
+     * credentials to be passed in to the server in order to
+     * authenticate the caller before creating the
+     * <code>RMIConnection</code>.  Can be null.
+     *
+     * @return the newly-created <code>RMIConnection</code>.  This is
+     * usually the object created by <code>makeClient</code>, though
+     * an implementation may choose to wrap that object in another
+     * object implementing <code>RMIConnection</code>.
+     *
+     * @exception IOException if the new client object cannot be
+     * created or exported.
+     *
+     * @exception SecurityException if the given credentials do not allow
+     * the server to authenticate the user successfully.
+     *
+     * @exception IllegalStateException if {@link #getMBeanServer()}
+     * is null.
+     */
+    public RMIConnection newClient(Object credentials) throws IOException {
+        return doNewClient(credentials);
+    }
+
+    /**
+     * This method could be overridden by subclasses defined in this package
+     * to perform additional operations specific to the underlying transport
+     * before creating the new client connection.
+     */
+    RMIConnection doNewClient(Object credentials) throws IOException {
+        final boolean tracing = logger.traceOn();
+
+        if (tracing) logger.trace("newClient","making new client");
+
+        if (getMBeanServer() == null)
+            throw new IllegalStateException("Not attached to an MBean server");
+
+        Subject subject = null;
+        JMXAuthenticator authenticator =
+            (JMXAuthenticator) env.get(JMXConnectorServer.AUTHENTICATOR);
+        if (authenticator == null) {
+            /*
+             * Create the JAAS-based authenticator only if authentication
+             * has been enabled
+             */
+            if (env.get("jmx.remote.x.password.file") != null ||
+                env.get("jmx.remote.x.login.config") != null) {
+                authenticator = new JMXPluggableAuthenticator(env);
+            }
+        }
+        if (authenticator != null) {
+            if (tracing) logger.trace("newClient","got authenticator: " +
+                               authenticator.getClass().getName());
+            try {
+                subject = authenticator.authenticate(credentials);
+            } catch (SecurityException e) {
+                logger.trace("newClient", "Authentication failed: " + e);
+                throw e;
+            }
+        }
+
+        if (tracing) {
+            if (subject != null)
+                logger.trace("newClient","subject is not null");
+            else logger.trace("newClient","no subject");
+        }
+
+        final String connectionId = makeConnectionId(getProtocol(), subject);
+
+        if (tracing)
+            logger.trace("newClient","making new connection: " + connectionId);
+
+        RMIConnection client = makeClient(connectionId, subject);
+
+        dropDeadReferences();
+        WeakReference<RMIConnection> wr = new WeakReference<RMIConnection>(client);
+        synchronized (clientList) {
+            clientList.add(wr);
+        }
+
+        connServer.connectionOpened(connectionId, "Connection opened", null);
+
+        synchronized (clientList) {
+            if (!clientList.contains(wr)) {
+                // can be removed only by a JMXConnectionNotification listener
+                throw new IOException("The connection is refused.");
+            }
+        }
+
+        if (tracing)
+            logger.trace("newClient","new connection done: " + connectionId );
+
+        return client;
+    }
+
+    /**
+     * <p>Creates a new client connection.  This method is called by
+     * the public method {@link #newClient(Object)}.</p>
+     *
+     * @param connectionId the ID of the new connection.  Every
+     * connection opened by this connector server will have a
+     * different ID.  The behavior is unspecified if this parameter is
+     * null.
+     *
+     * @param subject the authenticated subject.  Can be null.
+     *
+     * @return the newly-created <code>RMIConnection</code>.
+     *
+     * @exception IOException if the new client object cannot be
+     * created or exported.
+     */
+    protected abstract RMIConnection makeClient(String connectionId,
+                                                Subject subject)
+            throws IOException;
+
+    /**
+     * <p>Closes a client connection made by {@link #makeClient makeClient}.
+     *
+     * @param client a connection previously returned by
+     * <code>makeClient</code> on which the <code>closeClient</code>
+     * method has not previously been called.  The behavior is
+     * unspecified if these conditions are violated, including the
+     * case where <code>client</code> is null.
+     *
+     * @exception IOException if the client connection cannot be
+     * closed.
+     */
+    protected abstract void closeClient(RMIConnection client)
+            throws IOException;
+
+    /**
+     * <p>Returns the protocol string for this object.  The string is
+     * <code>rmi</code> for RMI/JRMP.
+     *
+     * @return the protocol string for this object.
+     */
+    protected abstract String getProtocol();
+
+    /**
+     * <p>Method called when a client connection created by {@link
+     * #makeClient makeClient} is closed.  A subclass that defines
+     * <code>makeClient</code> must arrange for this method to be
+     * called when the resultant object's {@link RMIConnection#close()
+     * close} method is called.  This enables it to be removed from
+     * the <code>RMIServerImpl</code>'s list of connections.  It is
+     * not an error for <code>client</code> not to be in that
+     * list.</p>
+     *
+     * <p>After removing <code>client</code> from the list of
+     * connections, this method calls {@link #closeClient
+     * closeClient(client)}.</p>
+     *
+     * @param client the client connection that has been closed.
+     *
+     * @exception IOException if {@link #closeClient} throws this
+     * exception.
+     *
+     * @exception NullPointerException if <code>client</code> is null.
+     */
+    protected void clientClosed(RMIConnection client) throws IOException {
+        final boolean debug = logger.debugOn();
+
+        if (debug) logger.trace("clientClosed","client="+client);
+
+        if (client == null)
+            throw new NullPointerException("Null client");
+
+        synchronized (clientList) {
+            dropDeadReferences();
+            for (Iterator<WeakReference<RMIConnection>> it = clientList.iterator();
+                 it.hasNext(); ) {
+                WeakReference<RMIConnection> wr = it.next();
+                if (wr.get() == client) {
+                    it.remove();
+                    break;
+                }
+            }
+            /* It is not a bug for this loop not to find the client.  In
+               our close() method, we remove a client from the list before
+               calling its close() method.  */
+        }
+
+        if (debug) logger.trace("clientClosed", "closing client.");
+        closeClient(client);
+
+        if (debug) logger.trace("clientClosed", "sending notif");
+        connServer.connectionClosed(client.getConnectionId(),
+                                    "Client connection closed", null);
+
+        if (debug) logger.trace("clientClosed","done");
+    }
+
+    /**
+     * <p>Closes this connection server.  This method first calls the
+     * {@link #closeServer()} method so that no new client connections
+     * will be accepted.  Then, for each remaining {@link
+     * RMIConnection} object returned by {@link #makeClient
+     * makeClient}, its {@link RMIConnection#close() close} method is
+     * called.</p>
+     *
+     * <p>The behavior when this method is called more than once is
+     * unspecified.</p>
+     *
+     * <p>If {@link #closeServer()} throws an
+     * <code>IOException</code>, the individual connections are
+     * nevertheless closed, and then the <code>IOException</code> is
+     * thrown from this method.</p>
+     *
+     * <p>If {@link #closeServer()} returns normally but one or more
+     * of the individual connections throws an
+     * <code>IOException</code>, then, after closing all the
+     * connections, one of those <code>IOException</code>s is thrown
+     * from this method.  If more than one connection throws an
+     * <code>IOException</code>, it is unspecified which one is thrown
+     * from this method.</p>
+     *
+     * @exception IOException if {@link #closeServer()} or one of the
+     * {@link RMIConnection#close()} calls threw
+     * <code>IOException</code>.
+     */
+    public synchronized void close() throws IOException {
+        final boolean tracing = logger.traceOn();
+        final boolean debug   = logger.debugOn();
+
+        if (tracing) logger.trace("close","closing");
+
+        IOException ioException = null;
+        try {
+            if (debug)   logger.debug("close","closing Server");
+            closeServer();
+        } catch (IOException e) {
+            if (tracing) logger.trace("close","Failed to close server: " + e);
+            if (debug)   logger.debug("close",e);
+            ioException = e;
+        }
+
+        if (debug)   logger.debug("close","closing Clients");
+        // Loop to close all clients
+        while (true) {
+            synchronized (clientList) {
+                if (debug) logger.debug("close","droping dead references");
+                dropDeadReferences();
+
+                if (debug) logger.debug("close","client count: "+clientList.size());
+                if (clientList.size() == 0)
+                    break;
+                /* Loop until we find a non-null client.  Because we called
+                   dropDeadReferences(), this will usually be the first
+                   element of the list, but a garbage collection could have
+                   happened in between.  */
+                for (Iterator<WeakReference<RMIConnection>> it = clientList.iterator();
+                     it.hasNext(); ) {
+                    WeakReference<RMIConnection> wr = it.next();
+                    RMIConnection client = wr.get();
+                    it.remove();
+                    if (client != null) {
+                        try {
+                            client.close();
+                        } catch (IOException e) {
+                            if (tracing)
+                                logger.trace("close","Failed to close client: " + e);
+                            if (debug) logger.debug("close",e);
+                            if (ioException == null)
+                                ioException = e;
+                        }
+                        break;
+                    }
+                }
+            }
+        }
+
+        if(notifBuffer != null)
+            notifBuffer.dispose();
+
+        if (ioException != null) {
+            if (tracing) logger.trace("close","close failed.");
+            throw ioException;
+        }
+
+        if (tracing) logger.trace("close","closed.");
+    }
+
+    /**
+     * <p>Called by {@link #close()} to close the connector server.
+     * After returning from this method, the connector server must
+     * not accept any new connections.</p>
+     *
+     * @exception IOException if the attempt to close the connector
+     * server failed.
+     */
+    protected abstract void closeServer() throws IOException;
+
+    private static synchronized String makeConnectionId(String protocol,
+                                                        Subject subject) {
+        connectionIdNumber++;
+
+        String clientHost = "";
+        try {
+            clientHost = RemoteServer.getClientHost();
+            /*
+             * According to the rules specified in the javax.management.remote
+             * package description, a numeric IPv6 address (detected by the
+             * presence of otherwise forbidden ":" character) forming a part
+             * of the connection id must be enclosed in square brackets.
+             */
+            if (clientHost.contains(":")) {
+                clientHost = "[" + clientHost + "]";
+            }
+        } catch (ServerNotActiveException e) {
+            logger.trace("makeConnectionId", "getClientHost", e);
+        }
+
+        final StringBuilder buf = new StringBuilder();
+        buf.append(protocol).append(":");
+        if (clientHost.length() > 0)
+            buf.append("//").append(clientHost);
+        buf.append(" ");
+        if (subject != null) {
+            Set<Principal> principals = subject.getPrincipals();
+            String sep = "";
+            for (Iterator<Principal> it = principals.iterator(); it.hasNext(); ) {
+                Principal p = it.next();
+                String name = p.getName().replace(' ', '_').replace(';', ':');
+                buf.append(sep).append(name);
+                sep = ";";
+            }
+        }
+        buf.append(" ").append(connectionIdNumber);
+        if (logger.traceOn())
+            logger.trace("newConnectionId","connectionId="+buf);
+        return buf.toString();
+    }
+
+    private void dropDeadReferences() {
+        synchronized (clientList) {
+            for (Iterator<WeakReference<RMIConnection>> it = clientList.iterator();
+                 it.hasNext(); ) {
+                WeakReference<RMIConnection> wr = it.next();
+                if (wr.get() == null)
+                    it.remove();
+            }
+        }
+    }
+
+    synchronized NotificationBuffer getNotifBuffer() {
+        //Notification buffer is lazily created when the first client connects
+        if(notifBuffer == null)
+            notifBuffer =
+                ArrayNotificationBuffer.getNotificationBuffer(mbeanServer,
+                                                              env);
+        return notifBuffer;
+    }
+
+    private static final ClassLogger logger =
+        new ClassLogger("javax.management.remote.rmi", "RMIServerImpl");
+
+    /** List of WeakReference values.  Each one references an
+        RMIConnection created by this object, or null if the
+        RMIConnection has been garbage-collected.  */
+    private final List<WeakReference<RMIConnection>> clientList =
+            new ArrayList<WeakReference<RMIConnection>>();
+
+    private ClassLoader cl;
+
+    private MBeanServer mbeanServer;
+
+    private final Map<String, ?> env;
+
+    private RMIConnectorServer connServer;
+
+    private static int connectionIdNumber;
+
+    private NotificationBuffer notifBuffer;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.management.rmi/share/classes/javax/management/remote/rmi/package.html	Thu Feb 02 16:50:46 2017 +0000
@@ -0,0 +1,340 @@
+<html>
+<head>
+    <title>RMI connector</title>
+<!--
+Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+-->
+</head>
+<body bgcolor="white">
+    <p>The RMI connector is a connector for the JMX Remote API that
+      uses RMI to transmit client requests to a remote MBean server.
+      This package defines the classes that the user of an RMI
+      connector needs to reference directly, for both the client and
+      server sides.  It also defines certain classes that the user
+      will not usually reference directly, but that must be defined so
+      that different implementations of the RMI connector can
+      interoperate.</p>
+
+    <p>The RMI connector supports the JRMP transport for RMI.</p>
+
+    <p>Like most connectors in the JMX Remote API, an RMI connector
+      usually has an address, which
+      is a {@link javax.management.remote.JMXServiceURL
+      JMXServiceURL}.  The protocol part of this address is
+      <code>rmi</code> for a connector that uses the default RMI
+      transport (JRMP).</p>
+
+    <p>There are two forms for RMI connector addresses:</p>
+
+    <ul>
+      <li>
+	In the <em>JNDI form</em>, the URL indicates <em>where to find
+	an RMI stub for the connector</em>.  This RMI stub is a Java
+	object of type {@link javax.management.remote.rmi.RMIServer
+	RMIServer} that gives remote access to the connector server.
+	With this address form, the RMI stub is obtained from an
+	external directory entry included in the URL.  An external
+	directory is any directory recognized by {@link javax.naming
+	JNDI}, typically the RMI registry, LDAP, or COS Naming.
+
+      <li>
+	In the <em>encoded form</em>, the URL directly includes the
+	information needed to connect to the connector server.  When
+	using RMI/JRMP, the encoded form is the serialized RMI stub
+	for the server object, encoded using BASE64 without embedded
+	newlines.
+    </ul>
+
+    <p>Addresses are covered in more detail below.</p>
+
+
+    <h3>Creating an RMI connector server</h3>
+
+    <p>The usual way to create an RMI connector server is to supply an
+      RMI connector address to the method {@link
+      javax.management.remote.JMXConnectorServerFactory#newJMXConnectorServer
+      JMXConnectorServerFactory.newJMXConnectorServer}.  The MBean
+      server to which the connector server is attached can be
+      specified as a parameter to that method.  Alternatively, the
+      connector server can be registered as an MBean in that MBean
+      server.</p>
+
+    <p>An RMI connector server can also be created by constructing an
+      instance of {@link
+      javax.management.remote.rmi.RMIConnectorServer
+      RMIConnectorServer}, explicitly or through the MBean server's
+      <code>createMBean</code> method.</p>
+
+    <h4>Choosing the RMI transport</h4>
+
+    <p>You can choose the RMI transport by specifying
+      <code>rmi</code> in the <code><em>protocol</em></code> part of the
+      <code>serviceURL</code> when creating the connector server.  You
+      can also create specialized connector servers by instantiating
+      an appropriate subclass of {@link
+      javax.management.remote.rmi.RMIServerImpl RMIServerImpl} and
+      supplying it to the <code>RMIConnectorServer</code>
+      constructor.</p>
+
+
+    <h4><a name="servergen">Connector addresses generated by the
+	server</a></h4>
+
+    <p>If the <code>serviceURL</code> you specify has an empty URL
+      path (after the optional host and port), or if you do not
+      specify a <code>serviceURL</code>, then the connector server
+      will fabricate a new <code>JMXServiceURL</code> that clients can
+      use to connect:</p>
+
+    <ul>
+
+      <li><p>If the <code>serviceURL</code> looks like:</p>
+
+	<pre>
+	<code>service:jmx:rmi://<em>host</em>:<em>port</em></code>
+	</pre>
+
+	<p>then the connector server will generate an {@link
+	javax.management.remote.rmi.RMIJRMPServerImpl
+	RMIJRMPServerImpl} and the returned <code>JMXServiceURL</code>
+	looks like:</p>
+
+	<pre>
+	<code>service:jmx:rmi://<em>host</em>:<em>port</em>/stub/<em>XXXX</em></code>
+	</pre>
+
+	<p>where <code><em>XXXX</em></code> is the serialized form of the
+	stub for the generated object, encoded in BASE64 without
+	newlines.</p>
+
+      <li><p>If there is no <code>serviceURL</code>, there must be a
+	user-provided <code>RMIServerImpl</code>.  The connector server
+        will generate a <code>JMXServiceURL</code> using the <code>rmi</code>
+	form.</p>
+
+    </ul>
+
+    <p>The <code><em>host</em></code> in a user-provided
+      <code>serviceURL</code> is optional.  If present, it is copied
+      into the generated <code>JMXServiceURL</code> but otherwise
+      ignored.  If absent, the generated <code>JXMServiceURL</code>
+      will have the local host name.</p>
+
+    <p>The <code><em>port</em></code> in a user-provided
+      <code>serviceURL</code> is also optional.  If present, it is
+      also copied into the generated <code>JMXServiceURL</code>;
+      otherwise, the generated <code>JMXServiceURL</code> has no port.
+      For an <code>serviceURL</code> using the <code>rmi</code>
+      protocol, the <code><em>port</em></code>, if present, indicates
+      what port the generated remote object should be exported on.  It
+      has no other effect.</p>
+
+    <p>If the user provides an <code>RMIServerImpl</code> rather than a
+      <code>JMXServiceURL</code>, then the generated
+      <code>JMXServiceURL</code> will have the local host name in its
+      <code><em>host</em></code> part and no
+      <code><em>port</em></code>.</p>
+
+
+    <h4><a name="directory">Connector addresses based on directory
+	entries</a></h4>
+
+    <p>As an alternative to the generated addresses just described,
+      the <code>serviceURL</code> address supplied when creating a
+      connector server can specify a <em>directory address</em> in
+      which to store the provided or generated <code>RMIServer</code>
+      stub.  This directory address is then used by both client and
+      server.</p>
+
+    <p>In this case, the <code>serviceURL</code> has the following form:</p>
+
+    <pre>
+    <code>service:jmx:rmi://<em>host</em>:<em>port</em>/jndi/<em>jndi-name</em></code>
+    </pre>
+
+    <p>Here, <code><em>jndi-name</em></code> is a string that can be
+      supplied to {@link javax.naming.InitialContext#bind
+      javax.naming.InitialContext.bind}.</p>
+
+    <p>As usual, the <code><em>host</em></code> and
+      <code>:<em>port</em></code> can be omitted.</p>
+
+    <p>The connector server will generate an
+      <code>RMIServerImpl</code> based on the protocol
+      (<code>rmi</code>) and the <code><em>port</em></code> if any.  When
+      the connector server is started, it will derive a stub from this
+      object using its {@link
+      javax.management.remote.rmi.RMIServerImpl#toStub toStub} method
+      and store the object using the given
+      <code><em>jndi-name</em></code>.  The properties defined by the
+      JNDI API are consulted as usual.</p>
+
+    <p>For example, if the <code>JMXServiceURL</code> is:
+
+      <pre>
+      <code>service:jmx:rmi://ignoredhost/jndi/rmi://myhost/myname</code>
+      </pre>
+
+      then the connector server will generate an
+      <code>RMIJRMPServerImpl</code> and store its stub using the JNDI
+      name
+
+      <pre>
+      <code>rmi://myhost/myname</code>
+      </pre>
+
+      which means entry <code>myname</code> in the RMI registry
+      running on the default port of host <code>myhost</code>.  Note
+      that the RMI registry only allows registration from the local
+      host.  So, in this case, <code>myhost</code> must be the name
+      (or a name) of the host that the connector server is running
+      on.
+
+    <p>In this <code>JMXServiceURL</code>, the first <code>rmi:</code>
+      specifies the RMI
+      connector, while the second <code>rmi:</code> specifies the RMI
+      registry.
+
+    <p>As another example, if the <code>JMXServiceURL</code> is:
+
+      <pre>
+      <code>service:jmx:rmi://ignoredhost/jndi/ldap://dirhost:9999/cn=this,ou=that</code>
+      </pre>
+
+      then the connector server will generate an
+      <code>RMIJRMPServerImpl</code> and store its stub using the JNDI
+      name
+
+      <pre>
+      <code>ldap://dirhost:9999/cn=this,ou=that</code>
+      </pre>
+
+      which means entry <code>cn=this,ou=that</code> in the LDAP
+      directory running on port 9999 of host <code>dirhost</code>.
+
+    <p>If the <code>JMXServiceURL</code> is:
+
+      <pre>
+      <code>service:jmx:rmi://ignoredhost/jndi/cn=this,ou=that</code>
+      </pre>
+
+      then the connector server will generate an
+      <code>RMIJRMPServerImpl</code> and store its stub using the JNDI
+      name
+
+      <pre>
+      <code>cn=this,ou=that</code>
+      </pre>
+
+      For this case to work, the JNDI API must have been configured
+      appropriately to supply the information about what directory to
+      use.
+
+    <p>In these examples, the host name <code>ignoredhost</code> is
+      not used by the connector server or its clients.  It can be
+      omitted, for example:</p>
+
+      <pre>
+      <code>service:jmx:rmi:///jndi/cn=this,ou=that</code>
+      </pre>
+
+    <p>However, it is good practice to use the name of the host
+      where the connector server is running.  This is often different
+      from the name of the directory host.</p>
+
+
+    <h4>Connector server attributes</h4>
+
+    <p>When using the default JRMP transport, RMI socket factories can
+      be specified using the attributes
+      <code>jmx.remote.rmi.client.socket.factory</code> and
+      <code>jmx.remote.rmi.server.socket.factory</code> in the
+      <code>environment</code> given to the
+      <code>RMIConnectorServer</code> constructor.  The values of these
+      attributes must be of type {@link
+      java.rmi.server.RMIClientSocketFactory} and {@link
+      java.rmi.server.RMIServerSocketFactory}, respectively.  These
+      factories are used when creating the RMI objects associated with
+      the connector.</p>
+
+    <h3>Creating an RMI connector client</h3>
+
+    <p>An RMI connector client is usually constructed using {@link
+      javax.management.remote.JMXConnectorFactory}, with a
+      <code>JMXServiceURL</code> that has <code>rmi</code> as its protocol.</p>
+
+    <p>If the <code>JMXServiceURL</code> was generated by the server,
+      as described above under <a href="#servergen">"connector
+      addresses generated by the server"</a>, then the client will
+      need to obtain it directly or indirectly from the server.
+      Typically, the server makes the <code>JMXServiceURL</code>
+      available by storing it in a file or a lookup service.</p>
+
+    <p>If the <code>JMXServiceURL</code> uses the directory syntax, as
+      described above under <a href="#directory">"connector addresses
+      based on directory entries"</a>, then the client may obtain it
+      as just explained, or client and server may both know the
+      appropriate directory entry to use.  For example, if the
+      connector server for the Whatsit agent uses the entry
+      <code>whatsit-agent-connector</code> in the RMI registry on host
+      <code>myhost</code>, then client and server can both know
+      that the appropriate <code>JMXServiceURL</code> is:</p>
+
+    <pre>
+    <code>service:jmx:rmi:///jndi/rmi://myhost/whatsit-agent-connector</code>
+    </pre>
+
+    <p>If you have an RMI stub of type {@link
+      javax.management.remote.rmi.RMIServer RMIServer}, you can
+      construct an RMI connection directly by using the appropriate
+      constructor of {@link javax.management.remote.rmi.RMIConnector
+      RMIConnector}.</p>
+
+    <h3>Dynamic code downloading</h3>
+
+    <p>If an RMI connector client or server receives from its peer an
+      instance of a class that it does not know, and if dynamic code
+      downloading is active for the RMI connection, then the class can
+      be downloaded from a codebase specified by the peer.  The
+      article <a
+    href="{@docRoot}/../technotes/guides/rmi/codebase.html"><em>Dynamic
+    code downloading using Java RMI</em></a> explains this in more
+    detail.</p>
+
+
+    @see <a href="{@docRoot}/../technotes/guides/rmi/index.html">
+	Java&trade; Remote Method
+	Invocation (RMI)</a>
+
+    @see <a href="{@docRoot}/../technotes/guides/jndi/index.html">
+	Java Naming and Directory Interface&trade; (JNDI)</a>
+
+    @see <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045,
+    section 6.8, "Base64 Content-Transfer-Encoding"</a>
+
+
+    @since 1.5
+
+  </body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.management.rmi/share/classes/module-info.java	Thu Feb 02 16:50:46 2017 +0000
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Defines the RMI Connector for the Java Management Extensions (JMX) Remote API.
+ * <P>
+ * The {@linkplain javax.management.remote.rmi RMI connector} is a connector
+ * for the JMX Remote API that uses RMI to transmit client requests to a remote
+ * MBean server.
+ *
+ * @provides javax.management.remote.JMXConnectorProvider
+ *           A provider of {@code JMXConnector} for the RMI protocol.<br>
+ *           Instances of {@code JMXConnector} using the RMI protocol
+ *           are usually created by the {@link
+ *           javax.management.remote.JMXConnectorFactory} which will locate
+ *           and load the appropriate {@code JMXConnectorProvider} service
+ *           implementation for the given protocol.
+ *
+ * @provides javax.management.remote.JMXConnectorServerProvider
+ *           A provider of {@code JMXConnectorServer} for the RMI protocol.<br>
+ *           Instances of {@code JMXConnectorServer} using the RMI protocol
+ *           are usually created by the {@link
+ *           javax.management.remote.JMXConnectorServerFactory} which will locate
+ *           and load the appropriate {@code JMXConnectorServerProvider} service
+ *           implementation for the given protocol.
+ *
+ */
+module java.management.rmi {
+
+    requires transitive java.management;
+    requires transitive java.rmi;
+    requires java.naming;
+
+    exports javax.management.remote.rmi;
+
+    // The qualified export below is required to preserve backward
+    // compatibility for the legacy case where an ordered list
+    // of package prefixes can be specified to the factory.
+    exports com.sun.jmx.remote.protocol.rmi to java.management;
+
+    // jdk.management.agent needs to create an RMIExporter instance.
+    exports com.sun.jmx.remote.internal.rmi to jdk.management.agent;
+
+    // The java.management.rmi module provides implementations
+    // of the JMXConnectorProvider and JMXConnectorServerProvider
+    // services supporting the RMI protocol.
+    provides javax.management.remote.JMXConnectorProvider
+        with com.sun.jmx.remote.protocol.rmi.ClientProvider;
+    provides javax.management.remote.JMXConnectorServerProvider
+        with com.sun.jmx.remote.protocol.rmi.ServerProvider;
+
+}
--- a/jdk/src/java.management/share/classes/com/sun/jmx/remote/internal/ClientNotifForwarder.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/src/java.management/share/classes/com/sun/jmx/remote/internal/ClientNotifForwarder.java	Thu Feb 02 16:50:46 2017 +0000
@@ -52,7 +52,6 @@
 import com.sun.jmx.remote.util.ClassLogger;
 import com.sun.jmx.remote.util.EnvHelp;
 import java.lang.reflect.UndeclaredThrowableException;
-import java.rmi.UnmarshalException;
 import java.util.concurrent.RejectedExecutionException;
 
 
@@ -633,7 +632,7 @@
                 }
 
                 return nr;
-            } catch (ClassNotFoundException | NotSerializableException | UnmarshalException e) {
+            } catch (ClassNotFoundException | NotSerializableException e) {
                 logger.trace("NotifFetcher.fetchNotifs", e);
                 return fetchOneNotif();
             } catch (IOException ioe) {
@@ -705,7 +704,7 @@
                 try {
                     // 1 notif to skip possible missing class
                     result = cnf.fetchNotifs(startSequenceNumber, 1, 0L);
-                } catch (ClassNotFoundException | NotSerializableException | UnmarshalException e) {
+                } catch (ClassNotFoundException | NotSerializableException e) {
                     logger.warning("NotifFetcher.fetchOneNotif",
                                    "Failed to deserialize a notification: "+e.toString());
                     if (logger.traceOn()) {
--- a/jdk/src/java.management/share/classes/com/sun/jmx/remote/internal/ProxyRef.java	Thu Feb 02 12:28:23 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,103 +0,0 @@
-/*
- * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.jmx.remote.internal;
-
-import java.io.IOException;
-import java.io.ObjectInput;
-import java.io.ObjectOutput;
-import java.lang.reflect.Method;
-import java.rmi.Remote;
-import java.rmi.RemoteException;
-import java.rmi.server.RemoteObject;
-import java.rmi.server.RemoteRef;
-
-
-@SuppressWarnings("deprecation")
-public class ProxyRef implements RemoteRef {
-    private static final long serialVersionUID = -6503061366316814723L;
-
-    public ProxyRef(RemoteRef ref) {
-        this.ref = ref;
-    }
-
-    public void readExternal(ObjectInput in)
-            throws IOException, ClassNotFoundException {
-        ref.readExternal(in);
-    }
-
-    public void writeExternal(ObjectOutput out) throws IOException {
-        ref.writeExternal(out);
-    }
-
-    /**
-     * @deprecated
-     */
-    @Deprecated
-    public void invoke(java.rmi.server.RemoteCall call) throws Exception {
-        ref.invoke(call);
-    }
-
-    public Object invoke(Remote obj, Method method, Object[] params,
-                         long opnum) throws Exception {
-        return ref.invoke(obj, method, params, opnum);
-    }
-
-    /**
-     * @deprecated
-     */
-    @Deprecated
-    public void done(java.rmi.server.RemoteCall call) throws RemoteException {
-        ref.done(call);
-    }
-
-    public String getRefClass(ObjectOutput out) {
-        return ref.getRefClass(out);
-    }
-
-    /**
-     * @deprecated
-     */
-    @Deprecated
-    public java.rmi.server.RemoteCall newCall(RemoteObject obj,
-            java.rmi.server.Operation[] op, int opnum,
-                              long hash) throws RemoteException {
-        return ref.newCall(obj, op, opnum, hash);
-    }
-
-    public boolean remoteEquals(RemoteRef obj) {
-        return ref.remoteEquals(obj);
-    }
-
-    public int remoteHashCode() {
-        return ref.remoteHashCode();
-    }
-
-    public String remoteToString() {
-        return ref.remoteToString();
-    }
-
-    protected RemoteRef ref;
-}
--- a/jdk/src/java.management/share/classes/com/sun/jmx/remote/internal/RMIExporter.java	Thu Feb 02 12:28:23 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-/*
- * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.jmx.remote.internal;
-
-import java.rmi.NoSuchObjectException;
-import java.rmi.Remote;
-import java.rmi.RemoteException;
-import java.rmi.server.RMIClientSocketFactory;
-import java.rmi.server.RMIServerSocketFactory;
-import java.rmi.server.UnicastRemoteObject;
-
-/**
- * <p>Unpublished interface controlling how the RMI Connector Server
- * exports objects.  The RMIServerImpl object and each
- * RMIConnectionImpl object are exported using the exporter.  The
- * default exporter calls {@link
- * UnicastRemoteObject#exportObject(Remote, int,
- * RMIClientSocketFactory, RMIServerSocketFactory)} to export objects
- * and {@link UnicastRemoteObject#unexportObject(Remote, boolean)} to
- * unexport them.  A replacement exporter can be specified via the
- * {@link #EXPORTER_ATTRIBUTE} property in the environment Map passed
- * to the RMI connector server.</p>
- */
-public interface RMIExporter {
-    public static final String EXPORTER_ATTRIBUTE =
-        "com.sun.jmx.remote.rmi.exporter";
-
-    public Remote exportObject(Remote obj,
-                               int port,
-                               RMIClientSocketFactory csf,
-                               RMIServerSocketFactory ssf)
-            throws RemoteException;
-
-    public boolean unexportObject(Remote obj, boolean force)
-            throws NoSuchObjectException;
-}
--- a/jdk/src/java.management/share/classes/com/sun/jmx/remote/internal/Unmarshal.java	Thu Feb 02 12:28:23 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.jmx.remote.internal;
-
-import java.io.IOException;
-import java.rmi.MarshalledObject;
-
-public interface Unmarshal {
-    public Object get(MarshalledObject<?> mo)
-            throws IOException, ClassNotFoundException;
-}
--- a/jdk/src/java.management/share/classes/com/sun/jmx/remote/protocol/rmi/ClientProvider.java	Thu Feb 02 12:28:23 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2002, 2004, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.jmx.remote.protocol.rmi;
-
-import java.io.IOException;
-import java.net.MalformedURLException;
-import java.util.Map;
-
-import javax.management.remote.JMXConnectorProvider;
-import javax.management.remote.JMXConnector;
-import javax.management.remote.JMXServiceURL;
-import javax.management.remote.rmi.RMIConnector;
-
-public class ClientProvider implements JMXConnectorProvider {
-
-    public JMXConnector newJMXConnector(JMXServiceURL serviceURL,
-                                        Map<String,?> environment)
-            throws IOException {
-        if (!serviceURL.getProtocol().equals("rmi")) {
-            throw new MalformedURLException("Protocol not rmi: " +
-                                            serviceURL.getProtocol());
-        }
-        return new RMIConnector(serviceURL, environment);
-    }
-}
--- a/jdk/src/java.management/share/classes/com/sun/jmx/remote/protocol/rmi/ServerProvider.java	Thu Feb 02 12:28:23 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-/*
- * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.jmx.remote.protocol.rmi;
-
-import java.io.IOException;
-import java.net.MalformedURLException;
-import java.util.Map;
-
-import javax.management.MBeanServer;
-import javax.management.remote.JMXConnectorServer;
-import javax.management.remote.JMXConnectorServerProvider;
-import javax.management.remote.JMXServiceURL;
-import javax.management.remote.rmi.RMIConnectorServer;
-
-public class ServerProvider implements JMXConnectorServerProvider {
-
-    public JMXConnectorServer newJMXConnectorServer(JMXServiceURL serviceURL,
-                                                    Map<String,?> environment,
-                                                    MBeanServer mbeanServer)
-            throws IOException {
-        if (!serviceURL.getProtocol().equals("rmi")) {
-            throw new MalformedURLException("Protocol not rmi: " +
-                                            serviceURL.getProtocol());
-        }
-        return new RMIConnectorServer(serviceURL, environment, mbeanServer);
-    }
-
-}
--- a/jdk/src/java.management/share/classes/javax/management/remote/JMXConnectorFactory.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/src/java.management/share/classes/javax/management/remote/JMXConnectorFactory.java	Thu Feb 02 16:50:46 2017 +0000
@@ -27,13 +27,17 @@
 
 import com.sun.jmx.mbeanserver.Util;
 import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.lang.reflect.Module;
 import java.net.MalformedURLException;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
-import java.util.Iterator;
 import java.util.ServiceLoader;
+import java.util.ServiceLoader.Provider;
 import java.util.StringTokenizer;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 
@@ -332,25 +336,32 @@
 
         IOException exception = null;
         if (provider == null) {
+            Predicate<Provider<?>> systemProvider =
+                    JMXConnectorFactory::isSystemProvider;
             // Loader is null when context class loader is set to null
             // and no loader has been provided in map.
             // com.sun.jmx.remote.util.Service class extracted from j2se
             // provider search algorithm doesn't handle well null classloader.
+            JMXConnector connection = null;
             if (loader != null) {
                 try {
-                    JMXConnector connection =
-                        getConnectorAsService(loader, providerURL, envcopy);
-                    if (connection != null)
-                        return connection;
+                    connection = getConnectorAsService(loader,
+                                                       providerURL,
+                                                       envcopy,
+                                                       systemProvider.negate());
+                    if (connection != null) return connection;
                 } catch (JMXProviderException e) {
                     throw e;
                 } catch (IOException e) {
                     exception = e;
                 }
             }
-            provider = getProvider(protocol, PROTOCOL_PROVIDER_DEFAULT_PACKAGE,
-                            JMXConnectorFactory.class.getClassLoader(),
-                            providerClassName, targetInterface);
+            connection = getConnectorAsService(
+                             JMXConnectorFactory.class.getClassLoader(),
+                             providerURL,
+                             Collections.unmodifiableMap(envcopy),
+                             systemProvider);
+            if (connection != null) return connection;
         }
 
         if (provider == null) {
@@ -437,13 +448,6 @@
         return instance;
     }
 
-    static <T> Iterator<T> getProviderIterator(final Class<T> providerClass,
-                                               final ClassLoader loader) {
-       ServiceLoader<T> serviceLoader =
-                ServiceLoader.load(providerClass, loader);
-       return serviceLoader.iterator();
-    }
-
     private static ClassLoader wrap(final ClassLoader parent) {
         return parent != null ? AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
             @Override
@@ -459,44 +463,265 @@
         }) : null;
     }
 
+    /**
+     * Checks whether the given provider is our system provider for
+     * the RMI connector.
+     * If providers for additional protocols are added in the future
+     * then the name of their modules may need to be added here.
+     * System providers will be loaded only if no other provider is found.
+     * @param provider the provider to test.
+     * @return true if this provider is a default system provider.
+     */
+    static boolean isSystemProvider(Provider<?> provider) {
+        Module providerModule = provider.type().getModule();
+        return providerModule.isNamed()
+           && providerModule.getName().equals("java.management.rmi");
+    }
+
+    /**
+     * Creates a JMXConnector from the first JMXConnectorProvider service
+     * supporting the given url that can be loaded from the given loader.
+     * <p>
+     * Parses the list of JMXConnectorProvider services that can be loaded
+     * from the given loader, only retaining those that satisfy the given filter.
+     * Then for each provider, attempts to create a new JMXConnector.
+     * The first JMXConnector successfully created is returned.
+     * <p>
+     * The filter predicate is usually used to either exclude system providers
+     * or only retain system providers (see isSystemProvider(...) above).
+     *
+     * @param loader The ClassLoader to use when looking up an implementation
+     *        of the service. If null, then only installed services will be
+     *        considered.
+     *
+     * @param url The JMXServiceURL of the connector for which a provider is
+     *        requested.
+     *
+     * @param filter A filter used to exclude or return provider
+     *        implementations. Typically the filter will either exclude
+     *        system services (system default implementations) or only
+     *        retain those.
+     *        This can allow to first look for custom implementations (e.g.
+     *        deployed on the CLASSPATH with META-INF/services) and
+     *        then only default to system implementations.
+     *
+     * @throws IOException if no connector could not be instantiated, and
+     *         at least one provider threw an exception that wasn't a
+     *         {@code MalformedURLException} or a {@code JMProviderException}.
+     *
+     * @throws JMXProviderException if a provider for the protocol in
+     *         <code>url</code> was found, but couldn't create the connector
+     *         some reason.
+     *
+     * @return an instance of JMXConnector if a provider was found from
+     *         which one could be instantiated, {@code null} otherwise.
+     */
     private static JMXConnector getConnectorAsService(ClassLoader loader,
                                                       JMXServiceURL url,
-                                                      Map<String, ?> map)
+                                                      Map<String, ?> map,
+                                                      Predicate<Provider<?>> filter)
         throws IOException {
 
-        Iterator<JMXConnectorProvider> providers =
-                getProviderIterator(JMXConnectorProvider.class, loader);
-        JMXConnector connection;
-        IOException exception = null;
-        while (providers.hasNext()) {
-            JMXConnectorProvider provider = providers.next();
-            try {
-                connection = provider.newJMXConnector(url, map);
-                return connection;
-            } catch (JMXProviderException e) {
-                throw e;
-            } catch (Exception e) {
-                if (logger.traceOn())
-                    logger.trace("getConnectorAsService",
-                                 "URL[" + url +
-                                 "] Service provider exception: " + e);
-                if (!(e instanceof MalformedURLException)) {
-                    if (exception == null) {
-                        if (e instanceof IOException) {
-                            exception = (IOException) e;
-                        } else {
-                            exception = EnvHelp.initCause(
-                                new IOException(e.getMessage()), e);
+        final ConnectorFactory<JMXConnectorProvider, JMXConnector> factory =
+                (p) -> p.newJMXConnector(url, map);
+        return getConnectorAsService(JMXConnectorProvider.class, loader, url,
+                                     filter, factory);
+    }
+
+
+    /**
+     * A factory function that can create a connector from a provider.
+     * The pair (P,C) will be either one of:
+     * a. (JMXConnectorProvider, JMXConnector) or
+     * b. (JMXConnectorServerProvider, JMXConnectorServer)
+     */
+    @FunctionalInterface
+    static interface ConnectorFactory<P,C> {
+        public C apply(P provider) throws Exception;
+    }
+
+    /**
+     * An instance of ProviderFinder is used to traverse a
+     * {@code Stream<Provider<P>>} and find the first implementation of P
+     * that supports creating a connector C from the given JMXServiceURL.
+     * <p>
+     * The pair (P,C) will be either one of: <br>
+     * a. (JMXConnectorProvider, JMXConnector) or <br>
+     * b. (JMXConnectorServerProvider, JMXConnectorServer)
+     * <p>
+     * The first connector successfully created while traversing the stream
+     * is stored in the ProviderFinder instance. After that, the
+     * ProviderFinder::test method, if called, will always return false, skipping
+     * the remaining providers.
+     * <p>
+     * An instance of ProviderFinder is always expected to be used in conjunction
+     * with Stream::findFirst, so that the stream traversal is stopped as soon
+     * as a matching provider is found.
+     * <p>
+     * At the end of the stream traversal, the ProviderFinder::get method can be
+     * used to obtain the connector instance (an instance of C) that was created.
+     * If no connector could be created, and an exception was encountered while
+     * traversing the stream and attempting to create the connector, then that
+     * exception will be thrown by ProviderFinder::get, wrapped, if needed,
+     * inside an IOException.
+     * <p>
+     * If any JMXProviderException is encountered while traversing the stream and
+     * attempting to create the connector, that exception will be wrapped in an
+     * UncheckedIOException and thrown immediately within the stream, thus
+     * interrupting the traversal.
+     * <p>
+     * If no matching provider was found (no provider found or attempting
+     * factory.apply always returned null or threw a MalformedURLException,
+     * indicating the provider didn't support the protocol asked for by
+     * the JMXServiceURL), then ProviderFinder::get will simply return null.
+     */
+    private static final class ProviderFinder<P,C> implements Predicate<Provider<P>> {
+
+        final ConnectorFactory<P,C> factory;
+        final JMXServiceURL  url;
+        private IOException  exception = null;
+        private C connection = null;
+
+        ProviderFinder(ConnectorFactory<P,C> factory, JMXServiceURL url) {
+            this.factory = factory;
+            this.url = url;
+        }
+
+        /**
+         * Returns {@code true} for the first provider {@code sp} that can
+         * be used to obtain an instance of {@code C} from the given
+         * {@code factory}.
+         *
+         * @param sp a candidate provider for instantiating {@code C}.
+         *
+         * @throws UncheckedIOException if {@code sp} throws a
+         *         JMXProviderException. The JMXProviderException is set as the
+         *         root cause.
+         *
+         * @return {@code true} for the first provider {@code sp} for which
+         *         {@code C} could be instantiated, {@code false} otherwise.
+         */
+        public boolean test(Provider<P> sp) {
+            if (connection == null) {
+                P provider = sp.get();
+                try {
+                    connection = factory.apply(provider);
+                    return connection != null;
+                } catch (JMXProviderException e) {
+                    throw new UncheckedIOException(e);
+                } catch (Exception e) {
+                    if (logger.traceOn())
+                        logger.trace("getConnectorAsService",
+                             "URL[" + url +
+                             "] Service provider exception: " + e);
+                    if (!(e instanceof MalformedURLException)) {
+                        if (exception == null) {
+                            if (e instanceof IOException) {
+                                exception = (IOException) e;
+                            } else {
+                                exception = EnvHelp.initCause(
+                                    new IOException(e.getMessage()), e);
+                            }
                         }
                     }
                 }
-                continue;
+            }
+            return false;
+        }
+
+        /**
+         * Returns an instance of {@code C} if a provider was found from
+         * which {@code C} could be instantiated.
+         *
+         * @throws IOException if {@code C} could not be instantiated, and
+         *         at least one provider threw an exception that wasn't a
+         *         {@code MalformedURLException} or a {@code JMProviderException}.
+         *
+         * @return an instance of {@code C} if a provider was found from
+         *         which {@code C} could be instantiated, {@code null} otherwise.
+         */
+        C get() throws IOException {
+            if (connection != null) return connection;
+            else if (exception != null) throw exception;
+            else return null;
+        }
+    }
+
+    /**
+     * Creates a connector from a provider loaded from the ServiceLoader.
+     * <p>
+     * The pair (P,C) will be either one of: <br>
+     * a. (JMXConnectorProvider, JMXConnector) or <br>
+     * b. (JMXConnectorServerProvider, JMXConnectorServer)
+     *
+     * @param providerClass The service type for which an implementation
+     *        should be looked up from the {@code ServiceLoader}. This will
+     *        be either {@code JMXConnectorProvider.class} or
+     *        {@code JMXConnectorServerProvider.class}
+     *
+     * @param loader The ClassLoader to use when looking up an implementation
+     *        of the service. If null, then only installed services will be
+     *        considered.
+     *
+     * @param url The JMXServiceURL of the connector for which a provider is
+     *        requested.
+     *
+     * @param filter A filter used to exclude or return provider
+     *        implementations. Typically the filter will either exclude
+     *        system services (system default implementations) or only
+     *        retain those.
+     *        This can allow to first look for custom implementations (e.g.
+     *        deployed on the CLASSPATH with META-INF/services) and
+     *        then only default to system implementations.
+     *
+     * @param factory A functional factory that can attempt to create an
+     *        instance of connector {@code C} from a provider {@code P}.
+     *        Typically, this is a simple wrapper over {@code
+     *        JMXConnectorProvider::newJMXConnector} or {@code
+     *        JMXConnectorProviderServer::newJMXConnectorServer}.
+     *
+     * @throws IOException if {@code C} could not be instantiated, and
+     *         at least one provider {@code P} threw an exception that wasn't a
+     *         {@code MalformedURLException} or a {@code JMProviderException}.
+     *
+     * @throws JMXProviderException if a provider {@code P} for the protocol in
+     *         <code>url</code> was found, but couldn't create the connector
+     *         {@code C} for some reason.
+     *
+     * @return an instance of {@code C} if a provider {@code P} was found from
+     *         which one could be instantiated, {@code null} otherwise.
+     */
+    static <P,C> C getConnectorAsService(Class<P> providerClass,
+                                         ClassLoader loader,
+                                         JMXServiceURL url,
+                                         Predicate<Provider<?>> filter,
+                                         ConnectorFactory<P,C> factory)
+        throws IOException {
+
+        // sanity check
+        if (JMXConnectorProvider.class != providerClass
+            && JMXConnectorServerProvider.class != providerClass) {
+            // should never happen
+            throw new InternalError("Unsupported service interface: "
+                                    + providerClass.getName());
+        }
+
+        ServiceLoader<P> serviceLoader = loader == null
+                ? ServiceLoader.loadInstalled(providerClass)
+                : ServiceLoader.load(providerClass, loader);
+        Stream<Provider<P>> stream = serviceLoader.stream().filter(filter);
+        ProviderFinder<P,C> finder = new ProviderFinder<>(factory, url);
+
+        try {
+            stream.filter(finder).findFirst();
+            return finder.get();
+        } catch (UncheckedIOException e) {
+            if (e.getCause() instanceof JMXProviderException) {
+                throw (JMXProviderException) e.getCause();
+            } else {
+                throw e;
             }
         }
-        if (exception == null)
-            return null;
-        else
-            throw exception;
     }
 
     static <T> T getProvider(String protocol,
--- a/jdk/src/java.management/share/classes/javax/management/remote/JMXConnectorServerFactory.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/src/java.management/share/classes/javax/management/remote/JMXConnectorServerFactory.java	Thu Feb 02 16:50:46 2017 +0000
@@ -30,13 +30,16 @@
 import com.sun.jmx.remote.util.EnvHelp;
 
 import java.io.IOException;
+import java.io.UncheckedIOException;
 import java.net.MalformedURLException;
 import java.util.Collections;
 import java.util.HashMap;
-import java.util.Iterator;
 import java.util.Map;
+import java.util.ServiceLoader.Provider;
+import java.util.function.Predicate;
 
 import javax.management.MBeanServer;
+import javax.management.remote.JMXConnectorFactory.ConnectorFactory;
 
 /**
  * <p>Factory to create JMX API connector servers.  There
@@ -205,43 +208,15 @@
     }
 
     private static JMXConnectorServer
-        getConnectorServerAsService(ClassLoader loader,
-                                    JMXServiceURL url,
-                                    Map<String, ?> map,
-                                    MBeanServer mbs)
+        getConnectorServerAsService(ClassLoader loader, JMXServiceURL url,
+                                    Map<String, ?> map, MBeanServer mbs,
+                                    Predicate<Provider<?>> filter)
         throws IOException {
-        Iterator<JMXConnectorServerProvider> providers =
-                JMXConnectorFactory.
-                getProviderIterator(JMXConnectorServerProvider.class, loader);
-
-        IOException exception = null;
-        while (providers.hasNext()) {
-            try {
-                return providers.next().newJMXConnectorServer(url, map, mbs);
-            } catch (JMXProviderException e) {
-                throw e;
-            } catch (Exception e) {
-                if (logger.traceOn())
-                    logger.trace("getConnectorAsService",
-                                 "URL[" + url +
-                                 "] Service provider exception: " + e);
-                if (!(e instanceof MalformedURLException)) {
-                    if (exception == null) {
-                        if (e instanceof IOException) {
-                            exception = (IOException) e;
-                        } else {
-                            exception = EnvHelp.initCause(
-                                new IOException(e.getMessage()), e);
-                        }
-                    }
-                }
-                continue;
-            }
-        }
-        if (exception == null)
-            return null;
-        else
-            throw exception;
+        final ConnectorFactory<JMXConnectorServerProvider,JMXConnectorServer>
+              factory = (p) -> p.newJMXConnectorServer(url, map, mbs);
+        return JMXConnectorFactory.getConnectorAsService(
+                                     JMXConnectorServerProvider.class,
+                                     loader, url, filter, factory);
     }
 
     /**
@@ -309,18 +284,22 @@
                                             loader);
 
         IOException exception = null;
+        JMXConnectorServer connection = null;
         if (provider == null) {
+            Predicate<Provider<?>> systemProvider =
+                    JMXConnectorFactory::isSystemProvider;
             // Loader is null when context class loader is set to null
             // and no loader has been provided in map.
             // com.sun.jmx.remote.util.Service class extracted from j2se
             // provider search algorithm doesn't handle well null classloader.
             if (loader != null) {
                 try {
-                    JMXConnectorServer connection =
+                    connection =
                         getConnectorServerAsService(loader,
                                                     serviceURL,
                                                     envcopy,
-                                                    mbeanServer);
+                                                    mbeanServer,
+                                                    systemProvider.negate());
                     if (connection != null)
                         return connection;
                 } catch (JMXProviderException e) {
@@ -329,13 +308,13 @@
                     exception = e;
                 }
             }
-            provider =
-                JMXConnectorFactory.getProvider(
-                    protocol,
-                    PROTOCOL_PROVIDER_DEFAULT_PACKAGE,
-                    JMXConnectorFactory.class.getClassLoader(),
-                    providerClassName,
-                    targetInterface);
+            connection = getConnectorServerAsService(
+                            JMXConnectorFactory.class.getClassLoader(),
+                            serviceURL,
+                            Collections.unmodifiableMap(envcopy),
+                            mbeanServer,
+                            systemProvider);
+            if (connection != null) return connection;
         }
 
         if (provider == null) {
--- a/jdk/src/java.management/share/classes/javax/management/remote/rmi/NoCallStackClassLoader.java	Thu Feb 02 12:28:23 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,296 +0,0 @@
-/*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package javax.management.remote.rmi;
-
-import java.security.ProtectionDomain;
-
-/**
-    <p>A class loader that only knows how to define a limited number
-    of classes, and load a limited number of other classes through
-    delegation to another loader.  It is used to get around a problem
-    with Serialization, in particular as used by RMI. The JMX Remote API
-    defines exactly what class loader must be used to deserialize arguments on
-    the server, and return values on the client.  We communicate this class
-    loader to RMI by setting it as the context class loader.  RMI uses the
-    context class loader to load classes as it deserializes, which is what we
-    want.  However, before consulting the context class loader, it
-    looks up the call stack for a class with a non-null class loader,
-    and uses that if it finds one.  So, in the standalone version of
-    javax.management.remote, if the class you're looking for is known
-    to the loader of jmxremote.jar (typically the system class loader)
-    then that loader will load it.  This contradicts the class-loading
-    semantics required.
-
-    <p>We get around the problem by ensuring that the search up the
-    call stack will find a non-null class loader that doesn't load any
-    classes of interest, namely this one.  So even though this loader
-    is indeed consulted during deserialization, it never finds the
-    class being deserialized.  RMI then proceeds to use the context
-    class loader, as we require.
-
-    <p>This loader is constructed with the name and byte-code of one
-    or more classes that it defines, and a class-loader to which it
-    will delegate certain other classes required by that byte-code.
-    We construct the byte-code somewhat painstakingly, by compiling
-    the Java code directly, converting into a string, copying that
-    string into the class that needs this loader, and using the
-    stringToBytes method to convert it into the byte array.  We
-    compile with -g:none because there's not much point in having
-    line-number information and the like in these directly-encoded
-    classes.
-
-    <p>The referencedClassNames should contain the names of all
-    classes that are referenced by the classes defined by this loader.
-    It is not necessary to include standard J2SE classes, however.
-    Here, a class is referenced if it is the superclass or a
-    superinterface of a defined class, or if it is the type of a
-    field, parameter, or return value.  A class is not referenced if
-    it only appears in the throws clause of a method or constructor.
-    Of course, referencedClassNames should not contain any classes
-    that the user might want to deserialize, because the whole point
-    of this loader is that it does not find such classes.
-*/
-
-class NoCallStackClassLoader extends ClassLoader {
-    /** Simplified constructor when this loader only defines one class.  */
-    public NoCallStackClassLoader(String className,
-                                  byte[] byteCode,
-                                  String[] referencedClassNames,
-                                  ClassLoader referencedClassLoader,
-                                  ProtectionDomain protectionDomain) {
-        this(new String[] {className}, new byte[][] {byteCode},
-             referencedClassNames, referencedClassLoader, protectionDomain);
-    }
-
-    public NoCallStackClassLoader(String[] classNames,
-                                  byte[][] byteCodes,
-                                  String[] referencedClassNames,
-                                  ClassLoader referencedClassLoader,
-                                  ProtectionDomain protectionDomain) {
-        super(null);
-
-        /* Validation. */
-        if (classNames == null || classNames.length == 0
-            || byteCodes == null || classNames.length != byteCodes.length
-            || referencedClassNames == null || protectionDomain == null)
-            throw new IllegalArgumentException();
-        for (int i = 0; i < classNames.length; i++) {
-            if (classNames[i] == null || byteCodes[i] == null)
-                throw new IllegalArgumentException();
-        }
-        for (int i = 0; i < referencedClassNames.length; i++) {
-            if (referencedClassNames[i] == null)
-                throw new IllegalArgumentException();
-        }
-
-        this.classNames = classNames;
-        this.byteCodes = byteCodes;
-        this.referencedClassNames = referencedClassNames;
-        this.referencedClassLoader = referencedClassLoader;
-        this.protectionDomain = protectionDomain;
-    }
-
-    /* This method is called at most once per name.  Define the name
-     * if it is one of the classes whose byte code we have, or
-     * delegate the load if it is one of the referenced classes.
-     */
-    @Override
-    protected Class<?> findClass(String name) throws ClassNotFoundException {
-        // Note: classNames is guaranteed by the constructor to be non-null.
-        for (int i = 0; i < classNames.length; i++) {
-            if (name.equals(classNames[i])) {
-                return defineClass(classNames[i], byteCodes[i], 0,
-                                   byteCodes[i].length, protectionDomain);
-            }
-        }
-
-        /* If the referencedClassLoader is null, it is the bootstrap
-         * class loader, and there's no point in delegating to it
-         * because it's already our parent class loader.
-         */
-        if (referencedClassLoader != null) {
-            for (int i = 0; i < referencedClassNames.length; i++) {
-                if (name.equals(referencedClassNames[i]))
-                    return referencedClassLoader.loadClass(name);
-            }
-        }
-
-        throw new ClassNotFoundException(name);
-    }
-
-    private final String[] classNames;
-    private final byte[][] byteCodes;
-    private final String[] referencedClassNames;
-    private final ClassLoader referencedClassLoader;
-    private final ProtectionDomain protectionDomain;
-
-    /**
-     * <p>Construct a <code>byte[]</code> using the characters of the
-     * given <code>String</code>.  Only the low-order byte of each
-     * character is used.  This method is useful to reduce the
-     * footprint of classes that include big byte arrays (e.g. the
-     * byte code of other classes), because a string takes up much
-     * less space in a class file than the byte code to initialize a
-     * <code>byte[]</code> with the same number of bytes.</p>
-     *
-     * <p>We use just one byte per character even though characters
-     * contain two bytes.  The resultant output length is much the
-     * same: using one byte per character is shorter because it has
-     * more characters in the optimal 1-127 range but longer because
-     * it has more zero bytes (which are frequent, and are encoded as
-     * two bytes in classfile UTF-8).  But one byte per character has
-     * two key advantages: (1) you can see the string constants, which
-     * is reassuring, (2) you don't need to know whether the class
-     * file length is odd.</p>
-     *
-     * <p>This method differs from {@link String#getBytes()} in that
-     * it does not use any encoding.  So it is guaranteed that each
-     * byte of the result is numerically identical (mod 256) to the
-     * corresponding character of the input.
-     */
-    public static byte[] stringToBytes(String s) {
-        final int slen = s.length();
-        byte[] bytes = new byte[slen];
-        for (int i = 0; i < slen; i++)
-            bytes[i] = (byte) s.charAt(i);
-        return bytes;
-    }
-}
-
-/*
-
-You can use the following Emacs function to convert class files into
-strings to be used by the stringToBytes method above.  Select the
-whole (defun...) with the mouse and type M-x eval-region, or save it
-to a file and do M-x load-file.  Then visit the *.class file and do
-M-x class-string.
-
-;; class-string.el
-;; visit the *.class file with emacs, then invoke this function
-
-(defun class-string ()
-  "Construct a Java string whose bytes are the same as the current
-buffer.  The resultant string is put in a buffer called *string*,
-possibly with a numeric suffix like <2>.  From there it can be
-insert-buffer'd into a Java program."
-  (interactive)
-  (let* ((s (buffer-string))
-         (slen (length s))
-         (i 0)
-         (buf (generate-new-buffer "*string*")))
-    (set-buffer buf)
-    (insert "\"")
-    (while (< i slen)
-      (if (> (current-column) 61)
-          (insert "\"+\n\""))
-      (let ((c (aref s i)))
-        (insert (cond
-                 ((> c 126) (format "\\%o" c))
-                 ((= c ?\") "\\\"")
-                 ((= c ?\\) "\\\\")
-                 ((< c 33)
-                  (let ((nextc (if (< (1+ i) slen)
-                                   (aref s (1+ i))
-                                 ?\0)))
-                    (cond
-                     ((and (<= nextc ?7) (>= nextc ?0))
-                      (format "\\%03o" c))
-                     (t
-                      (format "\\%o" c)))))
-                 (t c))))
-      (setq i (1+ i)))
-    (insert "\"")
-    (switch-to-buffer buf)))
-
-Alternatively, the following class reads a class file and outputs a string
-that can be used by the stringToBytes method above.
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-
-public class BytesToString {
-
-    public static void main(String[] args) throws IOException {
-        File f = new File(args[0]);
-        int len = (int)f.length();
-        byte[] classBytes = new byte[len];
-
-        FileInputStream in = new FileInputStream(args[0]);
-        try {
-            int pos = 0;
-            for (;;) {
-                int n = in.read(classBytes, pos, (len-pos));
-                if (n < 0)
-                    throw new RuntimeException("class file changed??");
-                pos += n;
-                if (pos >= n)
-                    break;
-            }
-        } finally {
-            in.close();
-        }
-
-        int pos = 0;
-        boolean lastWasOctal = false;
-        for (int i=0; i<len; i++) {
-            int value = classBytes[i];
-            if (value < 0)
-                value += 256;
-            String s = null;
-            if (value == '\\')
-                s = "\\\\";
-            else if (value == '\"')
-                s = "\\\"";
-            else {
-                if ((value >= 32 && value < 127) && ((!lastWasOctal ||
-                    (value < '0' || value > '7')))) {
-                    s = Character.toString((char)value);
-                }
-            }
-            if (s == null) {
-                s = "\\" + Integer.toString(value, 8);
-                lastWasOctal = true;
-            } else {
-                lastWasOctal = false;
-            }
-            if (pos > 61) {
-                System.out.print("\"");
-                if (i<len)
-                    System.out.print("+");
-                System.out.println();
-                pos = 0;
-            }
-            if (pos == 0)
-                System.out.print("                \"");
-            System.out.print(s);
-            pos += s.length();
-        }
-        System.out.println("\"");
-    }
-}
-
-*/
--- a/jdk/src/java.management/share/classes/javax/management/remote/rmi/RMIConnection.java	Thu Feb 02 12:28:23 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1092 +0,0 @@
-/*
- * Copyright (c) 2002, 2008, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package javax.management.remote.rmi;
-
-import java.io.Closeable;
-import java.io.IOException;
-import java.rmi.MarshalledObject;
-import java.rmi.Remote;
-import java.util.Set;
-
-import javax.management.AttributeList;
-import javax.management.AttributeNotFoundException;
-import javax.management.InstanceAlreadyExistsException;
-import javax.management.InstanceNotFoundException;
-import javax.management.IntrospectionException;
-import javax.management.InvalidAttributeValueException;
-import javax.management.ListenerNotFoundException;
-import javax.management.MBeanException;
-import javax.management.MBeanInfo;
-import javax.management.MBeanRegistrationException;
-import javax.management.MBeanServerConnection;
-import javax.management.NotCompliantMBeanException;
-
-import javax.management.ObjectInstance;
-import javax.management.ObjectName;
-import javax.management.ReflectionException;
-import javax.management.RuntimeMBeanException;
-import javax.management.RuntimeOperationsException;
-import javax.management.remote.NotificationResult;
-import javax.security.auth.Subject;
-
-/**
- * <p>RMI object used to forward an MBeanServer request from a client
- * to its MBeanServer implementation on the server side.  There is one
- * Remote object implementing this interface for each remote client
- * connected to an RMI connector.</p>
- *
- * <p>User code does not usually refer to this interface.  It is
- * specified as part of the public API so that different
- * implementations of that API will interoperate.</p>
- *
- * <p>To ensure that client parameters will be deserialized at the
- * server side with the correct classloader, client parameters such as
- * parameters used to invoke a method are wrapped in a {@link
- * MarshalledObject}.  An implementation of this interface must first
- * get the appropriate class loader for the operation and its target,
- * then deserialize the marshalled parameters with this classloader.
- * Except as noted, a parameter that is a
- * <code>MarshalledObject</code> or <code>MarshalledObject[]</code>
- * must not be null; the behavior is unspecified if it is.</p>
- *
- * <p>Class loading aspects are detailed in the
- * <a href="{@docRoot}/../technotes/guides/jmx/JMX_1_4_specification.pdf">
- * JMX Specification, version 1.4</a> PDF document.</p>
- *
- * <p>Most methods in this interface parallel methods in the {@link
- * MBeanServerConnection} interface.  Where an aspect of the behavior
- * of a method is not specified here, it is the same as in the
- * corresponding <code>MBeanServerConnection</code> method.
- *
- * @since 1.5
- */
-/*
- * Notice that we omit the type parameter from MarshalledObject everywhere,
- * even though it would add useful information to the documentation.  The
- * reason is that it was only added in Mustang (Java SE 6), whereas versions
- * 1.4 and 2.0 of the JMX API must be implementable on Tiger per our
- * commitments for JSR 255.  This is also why we suppress rawtypes warnings.
- */
-@SuppressWarnings("rawtypes")
-public interface RMIConnection extends Closeable, Remote {
-    /**
-     * <p>Returns the connection ID.  This string is different for
-     * every open connection to a given RMI connector server.</p>
-     *
-     * @return the connection ID
-     *
-     * @see RMIConnector#connect RMIConnector.connect
-     *
-     * @throws IOException if a general communication exception occurred.
-     */
-    public String getConnectionId() throws IOException;
-
-    /**
-     * <p>Closes this connection.  On return from this method, the RMI
-     * object implementing this interface is unexported, so further
-     * remote calls to it will fail.</p>
-     *
-     * @throws IOException if the connection could not be closed,
-     * or the Remote object could not be unexported, or there was a
-     * communication failure when transmitting the remote close
-     * request.
-     */
-    public void close() throws IOException;
-
-    /**
-     * Handles the method {@link
-     * javax.management.MBeanServerConnection#createMBean(String,
-     * ObjectName)}.
-     *
-     * @param className The class name of the MBean to be instantiated.
-     * @param name The object name of the MBean. May be null.
-     * @param delegationSubject The <code>Subject</code> containing the
-     * delegation principals or <code>null</code> if the authentication
-     * principal is used instead.
-     *
-     * @return An <code>ObjectInstance</code>, containing the
-     * <code>ObjectName</code> and the Java class name of the newly
-     * instantiated MBean.  If the contained <code>ObjectName</code>
-     * is <code>n</code>, the contained Java class name is
-     * <code>{@link #getMBeanInfo getMBeanInfo(n)}.getClassName()</code>.
-     *
-     * @throws ReflectionException Wraps a
-     * <code>java.lang.ClassNotFoundException</code> or a
-     * <code>java.lang.Exception</code> that occurred
-     * when trying to invoke the MBean's constructor.
-     * @throws InstanceAlreadyExistsException The MBean is already
-     * under the control of the MBean server.
-     * @throws MBeanRegistrationException The
-     * <code>preRegister</code> (<code>MBeanRegistration</code>
-     * interface) method of the MBean has thrown an exception. The
-     * MBean will not be registered.
-     * @throws MBeanException The constructor of the MBean has
-     * thrown an exception.
-     * @throws NotCompliantMBeanException This class is not a JMX
-     * compliant MBean.
-     * @throws RuntimeOperationsException Wraps a
-     * <code>java.lang.IllegalArgumentException</code>: The className
-     * passed in parameter is null, the <code>ObjectName</code> passed
-     * in parameter contains a pattern or no <code>ObjectName</code>
-     * is specified for the MBean.
-     * @throws SecurityException if the client, or the delegated Subject
-     * if any, does not have permission to perform this operation.
-     * @throws IOException if a general communication exception occurred.
-     */
-    public ObjectInstance createMBean(String className,
-                                      ObjectName name,
-                                      Subject delegationSubject)
-        throws
-        ReflectionException,
-        InstanceAlreadyExistsException,
-        MBeanRegistrationException,
-        MBeanException,
-        NotCompliantMBeanException,
-        IOException;
-
-    /**
-     * Handles the method {@link
-     * javax.management.MBeanServerConnection#createMBean(String,
-     * ObjectName, ObjectName)}.
-     *
-     * @param className The class name of the MBean to be instantiated.
-     * @param name The object name of the MBean. May be null.
-     * @param loaderName The object name of the class loader to be used.
-     * @param delegationSubject The <code>Subject</code> containing the
-     * delegation principals or <code>null</code> if the authentication
-     * principal is used instead.
-     *
-     * @return An <code>ObjectInstance</code>, containing the
-     * <code>ObjectName</code> and the Java class name of the newly
-     * instantiated MBean.  If the contained <code>ObjectName</code>
-     * is <code>n</code>, the contained Java class name is
-     * <code>{@link #getMBeanInfo getMBeanInfo(n)}.getClassName()</code>.
-     *
-     * @throws ReflectionException Wraps a
-     * <code>java.lang.ClassNotFoundException</code> or a
-     * <code>java.lang.Exception</code> that occurred when trying to
-     * invoke the MBean's constructor.
-     * @throws InstanceAlreadyExistsException The MBean is already
-     * under the control of the MBean server.
-     * @throws MBeanRegistrationException The
-     * <code>preRegister</code> (<code>MBeanRegistration</code>
-     * interface) method of the MBean has thrown an exception. The
-     * MBean will not be registered.
-     * @throws MBeanException The constructor of the MBean has
-     * thrown an exception.
-     * @throws NotCompliantMBeanException This class is not a JMX
-     * compliant MBean.
-     * @throws InstanceNotFoundException The specified class loader
-     * is not registered in the MBean server.
-     * @throws RuntimeOperationsException Wraps a
-     * <code>java.lang.IllegalArgumentException</code>: The className
-     * passed in parameter is null, the <code>ObjectName</code> passed
-     * in parameter contains a pattern or no <code>ObjectName</code>
-     * is specified for the MBean.
-     * @throws SecurityException if the client, or the delegated Subject
-     * if any, does not have permission to perform this operation.
-     * @throws IOException if a general communication exception occurred.
-     */
-    public ObjectInstance createMBean(String className,
-                                      ObjectName name,
-                                      ObjectName loaderName,
-                                      Subject delegationSubject)
-        throws
-        ReflectionException,
-        InstanceAlreadyExistsException,
-        MBeanRegistrationException,
-        MBeanException,
-        NotCompliantMBeanException,
-        InstanceNotFoundException,
-        IOException;
-
-    /**
-     * Handles the method {@link
-     * javax.management.MBeanServerConnection#createMBean(String,
-     * ObjectName, Object[], String[])}.  The <code>Object[]</code>
-     * parameter is wrapped in a <code>MarshalledObject</code>.
-     *
-     * @param className The class name of the MBean to be instantiated.
-     * @param name The object name of the MBean. May be null.
-     * @param params An array containing the parameters of the
-     * constructor to be invoked, encapsulated into a
-     * <code>MarshalledObject</code>.  The encapsulated array can be
-     * null, equivalent to an empty array.
-     * @param signature An array containing the signature of the
-     * constructor to be invoked.  Can be null, equivalent to an empty
-     * array.
-     * @param delegationSubject The <code>Subject</code> containing the
-     * delegation principals or <code>null</code> if the authentication
-     * principal is used instead.
-     *
-     * @return An <code>ObjectInstance</code>, containing the
-     * <code>ObjectName</code> and the Java class name of the newly
-     * instantiated MBean.  If the contained <code>ObjectName</code>
-     * is <code>n</code>, the contained Java class name is
-     * <code>{@link #getMBeanInfo getMBeanInfo(n)}.getClassName()</code>.
-     *
-     * @throws ReflectionException Wraps a
-     * <code>java.lang.ClassNotFoundException</code> or a
-     * <code>java.lang.Exception</code> that occurred when trying to
-     * invoke the MBean's constructor.
-     * @throws InstanceAlreadyExistsException The MBean is already
-     * under the control of the MBean server.
-     * @throws MBeanRegistrationException The
-     * <code>preRegister</code> (<code>MBeanRegistration</code>
-     * interface) method of the MBean has thrown an exception. The
-     * MBean will not be registered.
-     * @throws MBeanException The constructor of the MBean has
-     * thrown an exception.
-     * @throws NotCompliantMBeanException This class is not a JMX
-     * compliant MBean.
-     * @throws RuntimeOperationsException Wraps a
-     * <code>java.lang.IllegalArgumentException</code>: The className
-     * passed in parameter is null, the <code>ObjectName</code> passed
-     * in parameter contains a pattern, or no <code>ObjectName</code>
-     * is specified for the MBean.
-     * @throws SecurityException if the client, or the delegated Subject
-     * if any, does not have permission to perform this operation.
-     * @throws IOException if a general communication exception occurred.
-     */
-    public ObjectInstance createMBean(String className,
-                                ObjectName name,
-                                MarshalledObject params,
-                                String signature[],
-                                Subject delegationSubject)
-        throws
-        ReflectionException,
-        InstanceAlreadyExistsException,
-        MBeanRegistrationException,
-        MBeanException,
-        NotCompliantMBeanException,
-        IOException;
-
-    /**
-     * Handles the method {@link
-     * javax.management.MBeanServerConnection#createMBean(String,
-     * ObjectName, ObjectName, Object[], String[])}.  The
-     * <code>Object[]</code> parameter is wrapped in a
-     * <code>MarshalledObject</code>.
-     *
-     * @param className The class name of the MBean to be instantiated.
-     * @param name The object name of the MBean. May be null.
-     * @param loaderName The object name of the class loader to be used.
-     * @param params An array containing the parameters of the
-     * constructor to be invoked, encapsulated into a
-     * <code>MarshalledObject</code>.  The encapsulated array can be
-     * null, equivalent to an empty array.
-     * @param signature An array containing the signature of the
-     * constructor to be invoked.  Can be null, equivalent to an empty
-     * array.
-     * @param delegationSubject The <code>Subject</code> containing the
-     * delegation principals or <code>null</code> if the authentication
-     * principal is used instead.
-     *
-     * @return An <code>ObjectInstance</code>, containing the
-     * <code>ObjectName</code> and the Java class name of the newly
-     * instantiated MBean.  If the contained <code>ObjectName</code>
-     * is <code>n</code>, the contained Java class name is
-     * <code>{@link #getMBeanInfo getMBeanInfo(n)}.getClassName()</code>.
-     *
-     * @throws ReflectionException Wraps a
-     * <code>java.lang.ClassNotFoundException</code> or a
-     * <code>java.lang.Exception</code> that occurred when trying to
-     * invoke the MBean's constructor.
-     * @throws InstanceAlreadyExistsException The MBean is already
-     * under the control of the MBean server.
-     * @throws MBeanRegistrationException The
-     * <code>preRegister</code> (<code>MBeanRegistration</code>
-     * interface) method of the MBean has thrown an exception. The
-     * MBean will not be registered.
-     * @throws MBeanException The constructor of the MBean has
-     * thrown an exception.
-     * @throws NotCompliantMBeanException This class is not a JMX
-     * compliant MBean.
-     * @throws InstanceNotFoundException The specified class loader
-     * is not registered in the MBean server.
-     * @throws RuntimeOperationsException Wraps a
-     * <code>java.lang.IllegalArgumentException</code>: The className
-     * passed in parameter is null, the <code>ObjectName</code> passed
-     * in parameter contains a pattern, or no <code>ObjectName</code>
-     * is specified for the MBean.
-     * @throws SecurityException if the client, or the delegated Subject
-     * if any, does not have permission to perform this operation.
-     * @throws IOException if a general communication exception occurred.
-     */
-    public ObjectInstance createMBean(String className,
-                                ObjectName name,
-                                ObjectName loaderName,
-                                MarshalledObject params,
-                                String signature[],
-                                Subject delegationSubject)
-        throws
-        ReflectionException,
-        InstanceAlreadyExistsException,
-        MBeanRegistrationException,
-        MBeanException,
-        NotCompliantMBeanException,
-        InstanceNotFoundException,
-        IOException;
-
-    /**
-     * Handles the method
-     * {@link javax.management.MBeanServerConnection#unregisterMBean(ObjectName)}.
-     *
-     * @param name The object name of the MBean to be unregistered.
-     * @param delegationSubject The <code>Subject</code> containing the
-     * delegation principals or <code>null</code> if the authentication
-     * principal is used instead.
-     *
-     * @throws InstanceNotFoundException The MBean specified is not
-     * registered in the MBean server.
-     * @throws MBeanRegistrationException The preDeregister
-     * ((<code>MBeanRegistration</code> interface) method of the MBean
-     * has thrown an exception.
-     * @throws RuntimeOperationsException Wraps a
-     * <code>java.lang.IllegalArgumentException</code>: The object
-     * name in parameter is null or the MBean you are when trying to
-     * unregister is the {@link javax.management.MBeanServerDelegate
-     * MBeanServerDelegate} MBean.
-     * @throws SecurityException if the client, or the delegated Subject
-     * if any, does not have permission to perform this operation.
-     * @throws IOException if a general communication exception occurred.
-     */
-    public void unregisterMBean(ObjectName name, Subject delegationSubject)
-        throws
-        InstanceNotFoundException,
-        MBeanRegistrationException,
-        IOException;
-
-    /**
-     * Handles the method
-     * {@link javax.management.MBeanServerConnection#getObjectInstance(ObjectName)}.
-     *
-     * @param name The object name of the MBean.
-     * @param delegationSubject The <code>Subject</code> containing the
-     * delegation principals or <code>null</code> if the authentication
-     * principal is used instead.
-     *
-     * @return The <code>ObjectInstance</code> associated with the MBean
-     * specified by <var>name</var>.  The contained <code>ObjectName</code>
-     * is <code>name</code> and the contained class name is
-     * <code>{@link #getMBeanInfo getMBeanInfo(name)}.getClassName()</code>.
-     *
-     * @throws InstanceNotFoundException The MBean specified is not
-     * registered in the MBean server.
-     * @throws RuntimeOperationsException Wraps a
-     * <code>java.lang.IllegalArgumentException</code>: The object
-     * name in parameter is null.
-     * @throws SecurityException if the client, or the delegated Subject
-     * if any, does not have permission to perform this operation.
-     * @throws IOException if a general communication exception occurred.
-     */
-    public ObjectInstance getObjectInstance(ObjectName name,
-                                            Subject delegationSubject)
-        throws InstanceNotFoundException, IOException;
-
-    /**
-     * Handles the method {@link
-     * javax.management.MBeanServerConnection#queryMBeans(ObjectName,
-     * QueryExp)}.  The <code>QueryExp</code> is wrapped in a
-     * <code>MarshalledObject</code>.
-     *
-     * @param name The object name pattern identifying the MBeans to
-     * be retrieved. If null or no domain and key properties are
-     * specified, all the MBeans registered will be retrieved.
-     * @param query The query expression to be applied for selecting
-     * MBeans, encapsulated into a <code>MarshalledObject</code>. If
-     * the <code>MarshalledObject</code> encapsulates a null value no
-     * query expression will be applied for selecting MBeans.
-     * @param delegationSubject The <code>Subject</code> containing the
-     * delegation principals or <code>null</code> if the authentication
-     * principal is used instead.
-     *
-     * @return A set containing the <code>ObjectInstance</code>
-     * objects for the selected MBeans.  If no MBean satisfies the
-     * query an empty list is returned.
-     *
-     * @throws SecurityException if the client, or the delegated Subject
-     * if any, does not have permission to perform this operation.
-     * @throws IOException if a general communication exception occurred.
-     */
-    public Set<ObjectInstance>
-        queryMBeans(ObjectName name,
-                    MarshalledObject query,
-                    Subject delegationSubject)
-        throws IOException;
-
-    /**
-     * Handles the method {@link
-     * javax.management.MBeanServerConnection#queryNames(ObjectName,
-     * QueryExp)}.  The <code>QueryExp</code> is wrapped in a
-     * <code>MarshalledObject</code>.
-     *
-     * @param name The object name pattern identifying the MBean names
-     * to be retrieved. If null or no domain and key properties are
-     * specified, the name of all registered MBeans will be retrieved.
-     * @param query The query expression to be applied for selecting
-     * MBeans, encapsulated into a <code>MarshalledObject</code>. If
-     * the <code>MarshalledObject</code> encapsulates a null value no
-     * query expression will be applied for selecting MBeans.
-     * @param delegationSubject The <code>Subject</code> containing the
-     * delegation principals or <code>null</code> if the authentication
-     * principal is used instead.
-     *
-     * @return A set containing the ObjectNames for the MBeans
-     * selected.  If no MBean satisfies the query, an empty list is
-     * returned.
-     *
-     * @throws SecurityException if the client, or the delegated Subject
-     * if any, does not have permission to perform this operation.
-     * @throws IOException if a general communication exception occurred.
-     */
-    public Set<ObjectName>
-        queryNames(ObjectName name,
-                   MarshalledObject query,
-                   Subject delegationSubject)
-        throws IOException;
-
-    /**
-     * Handles the method
-     * {@link javax.management.MBeanServerConnection#isRegistered(ObjectName)}.
-     *
-     * @param name The object name of the MBean to be checked.
-     * @param delegationSubject The <code>Subject</code> containing the
-     * delegation principals or <code>null</code> if the authentication
-     * principal is used instead.
-     *
-     * @return True if the MBean is already registered in the MBean
-     * server, false otherwise.
-     *
-     * @throws RuntimeOperationsException Wraps a
-     * <code>java.lang.IllegalArgumentException</code>: The object
-     * name in parameter is null.
-     * @throws SecurityException if the client, or the delegated Subject
-     * if any, does not have permission to perform this operation.
-     * @throws IOException if a general communication exception occurred.
-     */
-    public boolean isRegistered(ObjectName name, Subject delegationSubject)
-        throws IOException;
-
-    /**
-     * Handles the method
-     * {@link javax.management.MBeanServerConnection#getMBeanCount()}.
-     *
-     * @param delegationSubject The <code>Subject</code> containing the
-     * delegation principals or <code>null</code> if the authentication
-     * principal is used instead.
-     *
-     * @return the number of MBeans registered.
-     *
-     * @throws SecurityException if the client, or the delegated Subject
-     * if any, does not have permission to perform this operation.
-     * @throws IOException if a general communication exception occurred.
-     */
-    public Integer getMBeanCount(Subject delegationSubject)
-        throws IOException;
-
-    /**
-     * Handles the method {@link
-     * javax.management.MBeanServerConnection#getAttribute(ObjectName,
-     * String)}.
-     *
-     * @param name The object name of the MBean from which the
-     * attribute is to be retrieved.
-     * @param attribute A String specifying the name of the attribute
-     * to be retrieved.
-     * @param delegationSubject The <code>Subject</code> containing the
-     * delegation principals or <code>null</code> if the authentication
-     * principal is used instead.
-     *
-     * @return  The value of the retrieved attribute.
-     *
-     * @throws AttributeNotFoundException The attribute specified
-     * is not accessible in the MBean.
-     * @throws MBeanException Wraps an exception thrown by the
-     * MBean's getter.
-     * @throws InstanceNotFoundException The MBean specified is not
-     * registered in the MBean server.
-     * @throws ReflectionException Wraps a
-     * <code>java.lang.Exception</code> thrown when trying to invoke
-     * the getter.
-     * @throws RuntimeOperationsException Wraps a
-     * <code>java.lang.IllegalArgumentException</code>: The object
-     * name in parameter is null or the attribute in parameter is
-     * null.
-     * @throws RuntimeMBeanException Wraps a runtime exception thrown
-     * by the MBean's getter.
-     * @throws SecurityException if the client, or the delegated Subject
-     * if any, does not have permission to perform this operation.
-     * @throws IOException if a general communication exception occurred.
-     *
-     * @see #setAttribute
-     */
-    public Object getAttribute(ObjectName name,
-                               String attribute,
-                               Subject delegationSubject)
-        throws
-        MBeanException,
-        AttributeNotFoundException,
-        InstanceNotFoundException,
-        ReflectionException,
-        IOException;
-
-    /**
-     * Handles the method {@link
-     * javax.management.MBeanServerConnection#getAttributes(ObjectName,
-     * String[])}.
-     *
-     * @param name The object name of the MBean from which the
-     * attributes are retrieved.
-     * @param attributes A list of the attributes to be retrieved.
-     * @param delegationSubject The <code>Subject</code> containing the
-     * delegation principals or <code>null</code> if the authentication
-     * principal is used instead.
-     *
-     * @return The list of the retrieved attributes.
-     *
-     * @throws InstanceNotFoundException The MBean specified is not
-     * registered in the MBean server.
-     * @throws ReflectionException An exception occurred when
-     * trying to invoke the getAttributes method of a Dynamic MBean.
-     * @throws RuntimeOperationsException Wrap a
-     * <code>java.lang.IllegalArgumentException</code>: The object
-     * name in parameter is null or attributes in parameter is null.
-     * @throws SecurityException if the client, or the delegated Subject
-     * if any, does not have permission to perform this operation.
-     * @throws IOException if a general communication exception occurred.
-     *
-     * @see #setAttributes
-     */
-    public AttributeList getAttributes(ObjectName name,
-                                       String[] attributes,
-                                       Subject delegationSubject)
-        throws
-        InstanceNotFoundException,
-        ReflectionException,
-        IOException;
-
-    /**
-     * Handles the method {@link
-     * javax.management.MBeanServerConnection#setAttribute(ObjectName,
-     * Attribute)}.  The <code>Attribute</code> parameter is wrapped
-     * in a <code>MarshalledObject</code>.
-     *
-     * @param name The name of the MBean within which the attribute is
-     * to be set.
-     * @param attribute The identification of the attribute to be set
-     * and the value it is to be set to, encapsulated into a
-     * <code>MarshalledObject</code>.
-     * @param delegationSubject The <code>Subject</code> containing the
-     * delegation principals or <code>null</code> if the authentication
-     * principal is used instead.
-     *
-     * @throws InstanceNotFoundException The MBean specified is not
-     * registered in the MBean server.
-     * @throws AttributeNotFoundException The attribute specified
-     * is not accessible in the MBean.
-     * @throws InvalidAttributeValueException The value specified
-     * for the attribute is not valid.
-     * @throws MBeanException Wraps an exception thrown by the
-     * MBean's setter.
-     * @throws ReflectionException Wraps a
-     * <code>java.lang.Exception</code> thrown when trying to invoke
-     * the setter.
-     * @throws RuntimeOperationsException Wraps a
-     * <code>java.lang.IllegalArgumentException</code>: The object
-     * name in parameter is null or the attribute in parameter is
-     * null.
-     * @throws SecurityException if the client, or the delegated Subject
-     * if any, does not have permission to perform this operation.
-     * @throws IOException if a general communication exception occurred.
-     *
-     * @see #getAttribute
-     */
-    public void setAttribute(ObjectName name,
-                             MarshalledObject attribute,
-                             Subject delegationSubject)
-        throws
-        InstanceNotFoundException,
-        AttributeNotFoundException,
-        InvalidAttributeValueException,
-        MBeanException,
-        ReflectionException,
-        IOException;
-
-    /**
-     * Handles the method {@link
-     * javax.management.MBeanServerConnection#setAttributes(ObjectName,
-     * AttributeList)}.  The <code>AttributeList</code> parameter is
-     * wrapped in a <code>MarshalledObject</code>.
-     *
-     * @param name The object name of the MBean within which the
-     * attributes are to be set.
-     * @param attributes A list of attributes: The identification of
-     * the attributes to be set and the values they are to be set to,
-     * encapsulated into a <code>MarshalledObject</code>.
-     * @param delegationSubject The <code>Subject</code> containing the
-     * delegation principals or <code>null</code> if the authentication
-     * principal is used instead.
-     *
-     * @return The list of attributes that were set, with their new
-     * values.
-     *
-     * @throws InstanceNotFoundException The MBean specified is not
-     * registered in the MBean server.
-     * @throws ReflectionException An exception occurred when
-     * trying to invoke the getAttributes method of a Dynamic MBean.
-     * @throws RuntimeOperationsException Wraps a
-     * <code>java.lang.IllegalArgumentException</code>: The object
-     * name in parameter is null or attributes in parameter is null.
-     * @throws SecurityException if the client, or the delegated Subject
-     * if any, does not have permission to perform this operation.
-     * @throws IOException if a general communication exception occurred.
-     *
-     * @see #getAttributes
-     */
-    public AttributeList setAttributes(ObjectName name,
-                          MarshalledObject attributes,
-                          Subject delegationSubject)
-        throws
-        InstanceNotFoundException,
-        ReflectionException,
-        IOException;
-
-    /**
-     * Handles the method {@link
-     * javax.management.MBeanServerConnection#invoke(ObjectName,
-     * String, Object[], String[])}.  The <code>Object[]</code>
-     * parameter is wrapped in a <code>MarshalledObject</code>.
-     *
-     * @param name The object name of the MBean on which the method is
-     * to be invoked.
-     * @param operationName The name of the operation to be invoked.
-     * @param params An array containing the parameters to be set when
-     * the operation is invoked, encapsulated into a
-     * <code>MarshalledObject</code>.  The encapsulated array can be
-     * null, equivalent to an empty array.
-     * @param signature An array containing the signature of the
-     * operation. The class objects will be loaded using the same
-     * class loader as the one used for loading the MBean on which the
-     * operation was invoked.  Can be null, equivalent to an empty
-     * array.
-     * @param delegationSubject The <code>Subject</code> containing the
-     * delegation principals or <code>null</code> if the authentication
-     * principal is used instead.
-     *
-     * @return The object returned by the operation, which represents
-     * the result of invoking the operation on the MBean specified.
-     *
-     * @throws InstanceNotFoundException The MBean specified is not
-     * registered in the MBean server.
-     * @throws MBeanException Wraps an exception thrown by the
-     * MBean's invoked method.
-     * @throws ReflectionException Wraps a
-     * <code>java.lang.Exception</code> thrown while trying to invoke
-     * the method.
-     * @throws SecurityException if the client, or the delegated Subject
-     * if any, does not have permission to perform this operation.
-     * @throws IOException if a general communication exception occurred.
-     * @throws RuntimeOperationsException Wraps an {@link
-     * IllegalArgumentException} when <code>name</code> or
-     * <code>operationName</code> is null.
-     */
-    public Object invoke(ObjectName name,
-                         String operationName,
-                         MarshalledObject params,
-                         String signature[],
-                         Subject delegationSubject)
-        throws
-        InstanceNotFoundException,
-        MBeanException,
-        ReflectionException,
-        IOException;
-
-    /**
-     * Handles the method
-     * {@link javax.management.MBeanServerConnection#getDefaultDomain()}.
-     *
-     * @param delegationSubject The <code>Subject</code> containing the
-     * delegation principals or <code>null</code> if the authentication
-     * principal is used instead.
-     *
-     * @return the default domain.
-     *
-     * @throws SecurityException if the client, or the delegated Subject
-     * if any, does not have permission to perform this operation.
-     * @throws IOException if a general communication exception occurred.
-     */
-    public String getDefaultDomain(Subject delegationSubject)
-        throws IOException;
-
-    /**
-     * Handles the method
-     * {@link javax.management.MBeanServerConnection#getDomains()}.
-     *
-     * @param delegationSubject The <code>Subject</code> containing the
-     * delegation principals or <code>null</code> if the authentication
-     * principal is used instead.
-     *
-     * @return the list of domains.
-     *
-     * @throws SecurityException if the client, or the delegated Subject
-     * if any, does not have permission to perform this operation.
-     * @throws IOException if a general communication exception occurred.
-     */
-    public String[] getDomains(Subject delegationSubject)
-        throws IOException;
-
-    /**
-     * Handles the method
-     * {@link javax.management.MBeanServerConnection#getMBeanInfo(ObjectName)}.
-     *
-     * @param name The name of the MBean to analyze
-     * @param delegationSubject The <code>Subject</code> containing the
-     * delegation principals or <code>null</code> if the authentication
-     * principal is used instead.
-     *
-     * @return An instance of <code>MBeanInfo</code> allowing the
-     * retrieval of all attributes and operations of this MBean.
-     *
-     * @throws IntrospectionException An exception occurred during
-     * introspection.
-     * @throws InstanceNotFoundException The MBean specified was
-     * not found.
-     * @throws ReflectionException An exception occurred when
-     * trying to invoke the getMBeanInfo of a Dynamic MBean.
-     * @throws SecurityException if the client, or the delegated Subject
-     * if any, does not have permission to perform this operation.
-     * @throws IOException if a general communication exception occurred.
-     * @throws RuntimeOperationsException Wraps a
-     * <code>java.lang.IllegalArgumentException</code>: The object
-     * name in parameter is null.
-     */
-    public MBeanInfo getMBeanInfo(ObjectName name, Subject delegationSubject)
-        throws
-        InstanceNotFoundException,
-        IntrospectionException,
-        ReflectionException,
-        IOException;
-
-    /**
-     * Handles the method {@link
-     * javax.management.MBeanServerConnection#isInstanceOf(ObjectName,
-     * String)}.
-     *
-     * @param name The <code>ObjectName</code> of the MBean.
-     * @param className The name of the class.
-     * @param delegationSubject The <code>Subject</code> containing the
-     * delegation principals or <code>null</code> if the authentication
-     * principal is used instead.
-     *
-     * @return true if the MBean specified is an instance of the
-     * specified class according to the rules above, false otherwise.
-     *
-     * @throws InstanceNotFoundException The MBean specified is not
-     * registered in the MBean server.
-     * @throws SecurityException if the client, or the delegated Subject
-     * if any, does not have permission to perform this operation.
-     * @throws IOException if a general communication exception occurred.
-     * @throws RuntimeOperationsException Wraps a
-     * <code>java.lang.IllegalArgumentException</code>: The object
-     * name in parameter is null.
-     */
-    public boolean isInstanceOf(ObjectName name,
-                                String className,
-                                Subject delegationSubject)
-        throws InstanceNotFoundException, IOException;
-
-    /**
-     * Handles the method {@link
-     * javax.management.MBeanServerConnection#addNotificationListener(ObjectName,
-     * ObjectName, NotificationFilter, Object)}.  The
-     * <code>NotificationFilter</code> parameter is wrapped in a
-     * <code>MarshalledObject</code>.  The <code>Object</code>
-     * (handback) parameter is also wrapped in a
-     * <code>MarshalledObject</code>.
-     *
-     * @param name The name of the MBean on which the listener should
-     * be added.
-     * @param listener The object name of the listener which will
-     * handle the notifications emitted by the registered MBean.
-     * @param filter The filter object, encapsulated into a
-     * <code>MarshalledObject</code>. If filter encapsulated in the
-     * <code>MarshalledObject</code> has a null value, no filtering
-     * will be performed before handling notifications.
-     * @param handback The context to be sent to the listener when a
-     * notification is emitted, encapsulated into a
-     * <code>MarshalledObject</code>.
-     * @param delegationSubject The <code>Subject</code> containing the
-     * delegation principals or <code>null</code> if the authentication
-     * principal is used instead.
-     *
-     * @throws InstanceNotFoundException The MBean name of the
-     * notification listener or of the notification broadcaster does
-     * not match any of the registered MBeans.
-     * @throws RuntimeOperationsException Wraps an {@link
-     * IllegalArgumentException}.  The MBean named by
-     * <code>listener</code> exists but does not implement the
-     * {@link javax.management.NotificationListener} interface,
-     * or <code>name</code> or <code>listener</code> is null.
-     * @throws SecurityException if the client, or the delegated Subject
-     * if any, does not have permission to perform this operation.
-     * @throws IOException if a general communication exception occurred.
-     *
-     * @see #removeNotificationListener(ObjectName, ObjectName, Subject)
-     * @see #removeNotificationListener(ObjectName, ObjectName,
-     * MarshalledObject, MarshalledObject, Subject)
-     */
-    public void addNotificationListener(ObjectName name,
-                        ObjectName listener,
-                        MarshalledObject filter,
-                        MarshalledObject handback,
-                        Subject delegationSubject)
-        throws InstanceNotFoundException, IOException;
-
-    /**
-     * Handles the method {@link
-     * javax.management.MBeanServerConnection#removeNotificationListener(ObjectName,
-     * ObjectName)}.
-     *
-     * @param name The name of the MBean on which the listener should
-     * be removed.
-     * @param listener The object name of the listener to be removed.
-     * @param delegationSubject The <code>Subject</code> containing the
-     * delegation principals or <code>null</code> if the authentication
-     * principal is used instead.
-     *
-     * @throws InstanceNotFoundException The MBean name provided
-     * does not match any of the registered MBeans.
-     * @throws ListenerNotFoundException The listener is not
-     * registered in the MBean.
-     * @throws SecurityException if the client, or the delegated Subject
-     * if any, does not have permission to perform this operation.
-     * @throws IOException if a general communication exception occurred.
-     * @throws RuntimeOperationsException Wraps an {@link
-     * IllegalArgumentException} when <code>name</code> or
-     * <code>listener</code> is null.
-     *
-     * @see #addNotificationListener
-     */
-    public void removeNotificationListener(ObjectName name,
-                                           ObjectName listener,
-                                           Subject delegationSubject)
-        throws
-        InstanceNotFoundException,
-        ListenerNotFoundException,
-        IOException;
-
-    /**
-     * Handles the method {@link
-     * javax.management.MBeanServerConnection#removeNotificationListener(ObjectName,
-     * ObjectName, NotificationFilter, Object)}.  The
-     * <code>NotificationFilter</code> parameter is wrapped in a
-     * <code>MarshalledObject</code>.  The <code>Object</code>
-     * parameter is also wrapped in a <code>MarshalledObject</code>.
-     *
-     * @param name The name of the MBean on which the listener should
-     * be removed.
-     * @param listener A listener that was previously added to this
-     * MBean.
-     * @param filter The filter that was specified when the listener
-     * was added, encapsulated into a <code>MarshalledObject</code>.
-     * @param handback The handback that was specified when the
-     * listener was added, encapsulated into a <code>MarshalledObject</code>.
-     * @param delegationSubject The <code>Subject</code> containing the
-     * delegation principals or <code>null</code> if the authentication
-     * principal is used instead.
-     *
-     * @throws InstanceNotFoundException The MBean name provided
-     * does not match any of the registered MBeans.
-     * @throws ListenerNotFoundException The listener is not
-     * registered in the MBean, or it is not registered with the given
-     * filter and handback.
-     * @throws SecurityException if the client, or the delegated Subject
-     * if any, does not have permission to perform this operation.
-     * @throws IOException if a general communication exception occurred.
-     * @throws RuntimeOperationsException Wraps an {@link
-     * IllegalArgumentException} when <code>name</code> or
-     * <code>listener</code> is null.
-     *
-     * @see #addNotificationListener
-     */
-    public void removeNotificationListener(ObjectName name,
-                      ObjectName listener,
-                      MarshalledObject filter,
-                      MarshalledObject handback,
-                      Subject delegationSubject)
-        throws
-        InstanceNotFoundException,
-        ListenerNotFoundException,
-        IOException;
-
-    // Special Handling of Notifications -------------------------------------
-
-    /**
-     * <p>Handles the method {@link
-     * javax.management.MBeanServerConnection#addNotificationListener(ObjectName,
-     * NotificationListener, NotificationFilter, Object)}.</p>
-     *
-     * <p>Register for notifications from the given MBeans that match
-     * the given filters.  The remote client can subsequently retrieve
-     * the notifications using the {@link #fetchNotifications
-     * fetchNotifications} method.</p>
-     *
-     * <p>For each listener, the original
-     * <code>NotificationListener</code> and <code>handback</code> are
-     * kept on the client side; in order for the client to be able to
-     * identify them, the server generates and returns a unique
-     * <code>listenerID</code>.  This <code>listenerID</code> is
-     * forwarded with the <code>Notifications</code> to the remote
-     * client.</p>
-     *
-     * <p>If any one of the given (name, filter) pairs cannot be
-     * registered, then the operation fails with an exception, and no
-     * names or filters are registered.</p>
-     *
-     * @param names the <code>ObjectNames</code> identifying the
-     * MBeans emitting the Notifications.
-     * @param filters an array of marshalled representations of the
-     * <code>NotificationFilters</code>.  Elements of this array can
-     * be null.
-     * @param delegationSubjects the <code>Subjects</code> on behalf
-     * of which the listeners are being added.  Elements of this array
-     * can be null.  Also, the <code>delegationSubjects</code>
-     * parameter itself can be null, which is equivalent to an array
-     * of null values with the same size as the <code>names</code> and
-     * <code>filters</code> arrays.
-     *
-     * @return an array of <code>listenerIDs</code> identifying the
-     * local listeners.  This array has the same number of elements as
-     * the parameters.
-     *
-     * @throws IllegalArgumentException if <code>names</code> or
-     * <code>filters</code> is null, or if <code>names</code> contains
-     * a null element, or if the three arrays do not all have the same
-     * size.
-     * @throws ClassCastException if one of the elements of
-     * <code>filters</code> unmarshalls as a non-null object that is
-     * not a <code>NotificationFilter</code>.
-     * @throws InstanceNotFoundException if one of the
-     * <code>names</code> does not correspond to any registered MBean.
-     * @throws SecurityException if, for one of the MBeans, the
-     * client, or the delegated Subject if any, does not have
-     * permission to add a listener.
-     * @throws IOException if a general communication exception occurred.
-     */
-    public Integer[] addNotificationListeners(ObjectName[] names,
-                    MarshalledObject[] filters,
-                    Subject[] delegationSubjects)
-        throws InstanceNotFoundException, IOException;
-
-    /**
-     * <p>Handles the
-     * {@link javax.management.MBeanServerConnection#removeNotificationListener(ObjectName,NotificationListener)
-     * removeNotificationListener(ObjectName, NotificationListener)} and
-     * {@link javax.management.MBeanServerConnection#removeNotificationListener(ObjectName,NotificationListener,NotificationFilter,Object)
-     * removeNotificationListener(ObjectName, NotificationListener, NotificationFilter, Object)} methods.</p>
-     *
-     * <p>This method removes one or more
-     * <code>NotificationListener</code>s from a given MBean in the
-     * MBean server.</p>
-     *
-     * <p>The <code>NotificationListeners</code> are identified by the
-     * IDs which were returned by the {@link
-     * #addNotificationListeners(ObjectName[], MarshalledObject[],
-     * Subject[])} method.</p>
-     *
-     * @param name the <code>ObjectName</code> identifying the MBean
-     * emitting the Notifications.
-     * @param listenerIDs the list of the IDs corresponding to the
-     * listeners to remove.
-     * @param delegationSubject The <code>Subject</code> containing the
-     * delegation principals or <code>null</code> if the authentication
-     * principal is used instead.
-     *
-     * @throws InstanceNotFoundException if the given
-     * <code>name</code> does not correspond to any registered MBean.
-     * @throws ListenerNotFoundException if one of the listeners was
-     * not found on the server side.  This exception can happen if the
-     * MBean discarded a listener for some reason other than a call to
-     * <code>MBeanServer.removeNotificationListener</code>.
-     * @throws SecurityException if the client, or the delegated Subject
-     * if any, does not have permission to remove the listeners.
-     * @throws IOException if a general communication exception occurred.
-     * @throws IllegalArgumentException if <code>ObjectName</code> or
-     * <code>listenerIds</code> is null or if <code>listenerIds</code>
-     * contains a null element.
-     */
-    public void removeNotificationListeners(ObjectName name,
-                                            Integer[] listenerIDs,
-                                            Subject delegationSubject)
-        throws
-        InstanceNotFoundException,
-        ListenerNotFoundException,
-        IOException;
-
-    /**
-     * <p>Retrieves notifications from the connector server.  This
-     * method can block until there is at least one notification or
-     * until the specified timeout is reached.  The method can also
-     * return at any time with zero notifications.</p>
-     *
-     * <p>A notification can be included in the result if its sequence
-     * number is no less than <code>clientSequenceNumber</code> and
-     * this client has registered at least one listener for the MBean
-     * generating the notification, with a filter that accepts the
-     * notification.  Each listener that is interested in the
-     * notification is identified by an Integer ID that was returned
-     * by {@link #addNotificationListeners(ObjectName[],
-     * MarshalledObject[], Subject[])}.</p>
-     *
-     * @param clientSequenceNumber the first sequence number that the
-     * client is interested in.  If negative, it is interpreted as
-     * meaning the sequence number that the next notification will
-     * have.
-     *
-     * @param maxNotifications the maximum number of different
-     * notifications to return.  The <code>TargetedNotification</code>
-     * array in the returned <code>NotificationResult</code> can have
-     * more elements than this if the same notification appears more
-     * than once.  The behavior is unspecified if this parameter is
-     * negative.
-     *
-     * @param timeout the maximum time in milliseconds to wait for a
-     * notification to arrive.  This can be 0 to indicate that the
-     * method should not wait if there are no notifications, but
-     * should return at once.  It can be <code>Long.MAX_VALUE</code>
-     * to indicate that there is no timeout.  The behavior is
-     * unspecified if this parameter is negative.
-     *
-     * @return A <code>NotificationResult</code>.
-     *
-     * @throws IOException if a general communication exception occurred.
-     */
-    public NotificationResult fetchNotifications(long clientSequenceNumber,
-                                                 int maxNotifications,
-                                                 long timeout)
-            throws IOException;
-}
--- a/jdk/src/java.management/share/classes/javax/management/remote/rmi/RMIConnectionImpl.java	Thu Feb 02 12:28:23 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1834 +0,0 @@
-/*
- * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package javax.management.remote.rmi;
-
-import java.io.IOException;
-import java.rmi.MarshalledObject;
-import java.rmi.UnmarshalException;
-import java.rmi.server.Unreferenced;
-import java.security.AccessControlContext;
-import java.security.AccessController;
-import java.security.Permission;
-import java.security.Permissions;
-import java.security.PrivilegedAction;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
-import java.security.ProtectionDomain;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Map;
-import java.util.Set;
-
-import javax.management.*;
-import javax.management.remote.JMXServerErrorException;
-import javax.management.remote.NotificationResult;
-import javax.security.auth.Subject;
-import sun.reflect.misc.ReflectUtil;
-
-import static com.sun.jmx.mbeanserver.Util.cast;
-import com.sun.jmx.remote.internal.ServerCommunicatorAdmin;
-import com.sun.jmx.remote.internal.ServerNotifForwarder;
-import com.sun.jmx.remote.security.JMXSubjectDomainCombiner;
-import com.sun.jmx.remote.security.SubjectDelegator;
-import com.sun.jmx.remote.util.ClassLoaderWithRepository;
-import com.sun.jmx.remote.util.ClassLogger;
-import com.sun.jmx.remote.util.EnvHelp;
-import com.sun.jmx.remote.util.OrderClassLoaders;
-import javax.management.loading.ClassLoaderRepository;
-
-/**
- * <p>Implementation of the {@link RMIConnection} interface.  User
- * code will not usually reference this class.</p>
- *
- * @since 1.5
- */
-/*
- * Notice that we omit the type parameter from MarshalledObject everywhere,
- * even though it would add useful information to the documentation.  The
- * reason is that it was only added in Mustang (Java SE 6), whereas versions
- * 1.4 and 2.0 of the JMX API must be implementable on Tiger per our
- * commitments for JSR 255.
- */
-public class RMIConnectionImpl implements RMIConnection, Unreferenced {
-
-    /**
-     * Constructs a new {@link RMIConnection}. This connection can be
-     * used with the JRMP transport. This object does
-     * not export itself: it is the responsibility of the caller to
-     * export it appropriately (see {@link
-     * RMIJRMPServerImpl#makeClient(String,Subject)}).
-     *
-     * @param rmiServer The RMIServerImpl object for which this
-     * connection is created.  The behavior is unspecified if this
-     * parameter is null.
-     * @param connectionId The ID for this connection.  The behavior
-     * is unspecified if this parameter is null.
-     * @param defaultClassLoader The default ClassLoader to be used
-     * when deserializing marshalled objects.  Can be null, to signify
-     * the bootstrap class loader.
-     * @param subject the authenticated subject to be used for
-     * authorization.  Can be null, to signify that no subject has
-     * been authenticated.
-     * @param env the environment containing attributes for the new
-     * <code>RMIServerImpl</code>.  Can be null, equivalent to an
-     * empty map.
-     */
-    public RMIConnectionImpl(RMIServerImpl rmiServer,
-                             String connectionId,
-                             ClassLoader defaultClassLoader,
-                             Subject subject,
-                             Map<String,?> env) {
-        if (rmiServer == null || connectionId == null)
-            throw new NullPointerException("Illegal null argument");
-        if (env == null)
-            env = Collections.emptyMap();
-        this.rmiServer = rmiServer;
-        this.connectionId = connectionId;
-        this.defaultClassLoader = defaultClassLoader;
-
-        this.subjectDelegator = new SubjectDelegator();
-        this.subject = subject;
-        if (subject == null) {
-            this.acc = null;
-            this.removeCallerContext = false;
-        } else {
-            this.removeCallerContext =
-                SubjectDelegator.checkRemoveCallerContext(subject);
-            if (this.removeCallerContext) {
-                this.acc =
-                    JMXSubjectDomainCombiner.getDomainCombinerContext(subject);
-            } else {
-                this.acc =
-                    JMXSubjectDomainCombiner.getContext(subject);
-            }
-        }
-        this.mbeanServer = rmiServer.getMBeanServer();
-
-        final ClassLoader dcl = defaultClassLoader;
-
-        ClassLoaderRepository repository = AccessController.doPrivileged(
-            new PrivilegedAction<ClassLoaderRepository>() {
-                public ClassLoaderRepository run() {
-                    return mbeanServer.getClassLoaderRepository();
-                }
-            },
-            withPermissions(new MBeanPermission("*", "getClassLoaderRepository"))
-        );
-        this.classLoaderWithRepository = AccessController.doPrivileged(
-            new PrivilegedAction<ClassLoaderWithRepository>() {
-                public ClassLoaderWithRepository run() {
-                    return new ClassLoaderWithRepository(
-                        repository,
-                        dcl);
-                }
-            },
-            withPermissions(new RuntimePermission("createClassLoader"))
-        );
-
-        this.defaultContextClassLoader =
-            AccessController.doPrivileged(
-                new PrivilegedAction<ClassLoader>() {
-            @Override
-                    public ClassLoader run() {
-                        return new CombinedClassLoader(Thread.currentThread().getContextClassLoader(),
-                                dcl);
-                    }
-                });
-
-        serverCommunicatorAdmin = new
-          RMIServerCommunicatorAdmin(EnvHelp.getServerConnectionTimeout(env));
-
-        this.env = env;
-    }
-
-    private static AccessControlContext withPermissions(Permission ... perms){
-        Permissions col = new Permissions();
-
-        for (Permission thePerm : perms ) {
-            col.add(thePerm);
-        }
-
-        final ProtectionDomain pd = new ProtectionDomain(null, col);
-        return new AccessControlContext( new ProtectionDomain[] { pd });
-    }
-
-    private synchronized ServerNotifForwarder getServerNotifFwd() {
-        // Lazily created when first use. Mainly when
-        // addNotificationListener is first called.
-        if (serverNotifForwarder == null)
-            serverNotifForwarder =
-                new ServerNotifForwarder(mbeanServer,
-                                         env,
-                                         rmiServer.getNotifBuffer(),
-                                         connectionId);
-        return serverNotifForwarder;
-    }
-
-    public String getConnectionId() throws IOException {
-        // We should call reqIncomming() here... shouldn't we?
-        return connectionId;
-    }
-
-    public void close() throws IOException {
-        final boolean debug = logger.debugOn();
-        final String  idstr = (debug?"["+this.toString()+"]":null);
-
-        synchronized (this) {
-            if (terminated) {
-                if (debug) logger.debug("close",idstr + " already terminated.");
-                return;
-            }
-
-            if (debug) logger.debug("close",idstr + " closing.");
-
-            terminated = true;
-
-            if (serverCommunicatorAdmin != null) {
-                serverCommunicatorAdmin.terminate();
-            }
-
-            if (serverNotifForwarder != null) {
-                serverNotifForwarder.terminate();
-            }
-        }
-
-        rmiServer.clientClosed(this);
-
-        if (debug) logger.debug("close",idstr + " closed.");
-    }
-
-    public void unreferenced() {
-        logger.debug("unreferenced", "called");
-        try {
-            close();
-            logger.debug("unreferenced", "done");
-        } catch (IOException e) {
-            logger.fine("unreferenced", e);
-        }
-    }
-
-    //-------------------------------------------------------------------------
-    // MBeanServerConnection Wrapper
-    //-------------------------------------------------------------------------
-
-    public ObjectInstance createMBean(String className,
-                                      ObjectName name,
-                                      Subject delegationSubject)
-        throws
-        ReflectionException,
-        InstanceAlreadyExistsException,
-        MBeanRegistrationException,
-        MBeanException,
-        NotCompliantMBeanException,
-        IOException {
-        try {
-            final Object params[] =
-                new Object[] { className, name };
-
-            if (logger.debugOn())
-                logger.debug("createMBean(String,ObjectName)",
-                             "connectionId=" + connectionId +", className=" +
-                             className+", name=" + name);
-
-            return (ObjectInstance)
-                doPrivilegedOperation(
-                  CREATE_MBEAN,
-                  params,
-                  delegationSubject);
-        } catch (PrivilegedActionException pe) {
-            Exception e = extractException(pe);
-            if (e instanceof ReflectionException)
-                throw (ReflectionException) e;
-            if (e instanceof InstanceAlreadyExistsException)
-                throw (InstanceAlreadyExistsException) e;
-            if (e instanceof MBeanRegistrationException)
-                throw (MBeanRegistrationException) e;
-            if (e instanceof MBeanException)
-                throw (MBeanException) e;
-            if (e instanceof NotCompliantMBeanException)
-                throw (NotCompliantMBeanException) e;
-            if (e instanceof IOException)
-                throw (IOException) e;
-            throw newIOException("Got unexpected server exception: " + e, e);
-        }
-    }
-
-    public ObjectInstance createMBean(String className,
-                                      ObjectName name,
-                                      ObjectName loaderName,
-                                      Subject delegationSubject)
-        throws
-        ReflectionException,
-        InstanceAlreadyExistsException,
-        MBeanRegistrationException,
-        MBeanException,
-        NotCompliantMBeanException,
-        InstanceNotFoundException,
-        IOException {
-        try {
-            final Object params[] =
-                new Object[] { className, name, loaderName };
-
-            if (logger.debugOn())
-                logger.debug("createMBean(String,ObjectName,ObjectName)",
-                      "connectionId=" + connectionId
-                      +", className=" + className
-                      +", name=" + name
-                      +", loaderName=" + loaderName);
-
-            return (ObjectInstance)
-                doPrivilegedOperation(
-                  CREATE_MBEAN_LOADER,
-                  params,
-                  delegationSubject);
-        } catch (PrivilegedActionException pe) {
-            Exception e = extractException(pe);
-            if (e instanceof ReflectionException)
-                throw (ReflectionException) e;
-            if (e instanceof InstanceAlreadyExistsException)
-                throw (InstanceAlreadyExistsException) e;
-            if (e instanceof MBeanRegistrationException)
-                throw (MBeanRegistrationException) e;
-            if (e instanceof MBeanException)
-                throw (MBeanException) e;
-            if (e instanceof NotCompliantMBeanException)
-                throw (NotCompliantMBeanException) e;
-            if (e instanceof InstanceNotFoundException)
-                throw (InstanceNotFoundException) e;
-            if (e instanceof IOException)
-                throw (IOException) e;
-            throw newIOException("Got unexpected server exception: " + e, e);
-        }
-    }
-
-    @SuppressWarnings("rawtypes")  // MarshalledObject
-    public ObjectInstance createMBean(String className,
-                                      ObjectName name,
-                                      MarshalledObject params,
-                                      String signature[],
-                                      Subject delegationSubject)
-        throws
-        ReflectionException,
-        InstanceAlreadyExistsException,
-        MBeanRegistrationException,
-        MBeanException,
-        NotCompliantMBeanException,
-        IOException {
-
-        final Object[] values;
-        final boolean debug = logger.debugOn();
-
-        if (debug) logger.debug(
-                  "createMBean(String,ObjectName,Object[],String[])",
-                  "connectionId=" + connectionId
-                  +", unwrapping parameters using classLoaderWithRepository.");
-
-        values =
-            nullIsEmpty(unwrap(params, classLoaderWithRepository, Object[].class,delegationSubject));
-
-        try {
-            final Object params2[] =
-                new Object[] { className, name, values,
-                               nullIsEmpty(signature) };
-
-            if (debug)
-               logger.debug("createMBean(String,ObjectName,Object[],String[])",
-                             "connectionId=" + connectionId
-                             +", className=" + className
-                             +", name=" + name
-                             +", signature=" + strings(signature));
-
-            return (ObjectInstance)
-                doPrivilegedOperation(
-                  CREATE_MBEAN_PARAMS,
-                  params2,
-                  delegationSubject);
-        } catch (PrivilegedActionException pe) {
-            Exception e = extractException(pe);
-            if (e instanceof ReflectionException)
-                throw (ReflectionException) e;
-            if (e instanceof InstanceAlreadyExistsException)
-                throw (InstanceAlreadyExistsException) e;
-            if (e instanceof MBeanRegistrationException)
-                throw (MBeanRegistrationException) e;
-            if (e instanceof MBeanException)
-                throw (MBeanException) e;
-            if (e instanceof NotCompliantMBeanException)
-                throw (NotCompliantMBeanException) e;
-            if (e instanceof IOException)
-                throw (IOException) e;
-            throw newIOException("Got unexpected server exception: " + e, e);
-        }
-    }
-
-    @SuppressWarnings("rawtypes")  // MarshalledObject
-    public ObjectInstance createMBean(String className,
-                                 ObjectName name,
-                                 ObjectName loaderName,
-                                 MarshalledObject params,
-                                 String signature[],
-                                 Subject delegationSubject)
-        throws
-        ReflectionException,
-        InstanceAlreadyExistsException,
-        MBeanRegistrationException,
-        MBeanException,
-        NotCompliantMBeanException,
-        InstanceNotFoundException,
-        IOException {
-
-        final Object[] values;
-        final boolean debug = logger.debugOn();
-
-        if (debug) logger.debug(
-                 "createMBean(String,ObjectName,ObjectName,Object[],String[])",
-                 "connectionId=" + connectionId
-                 +", unwrapping params with MBean extended ClassLoader.");
-
-        values = nullIsEmpty(unwrap(params,
-                                    getClassLoader(loaderName),
-                                    defaultClassLoader,
-                                    Object[].class,delegationSubject));
-
-        try {
-            final Object params2[] =
-               new Object[] { className, name, loaderName, values,
-                              nullIsEmpty(signature) };
-
-           if (debug) logger.debug(
-                 "createMBean(String,ObjectName,ObjectName,Object[],String[])",
-                 "connectionId=" + connectionId
-                 +", className=" + className
-                 +", name=" + name
-                 +", loaderName=" + loaderName
-                 +", signature=" + strings(signature));
-
-            return (ObjectInstance)
-                doPrivilegedOperation(
-                  CREATE_MBEAN_LOADER_PARAMS,
-                  params2,
-                  delegationSubject);
-        } catch (PrivilegedActionException pe) {
-            Exception e = extractException(pe);
-            if (e instanceof ReflectionException)
-                throw (ReflectionException) e;
-            if (e instanceof InstanceAlreadyExistsException)
-                throw (InstanceAlreadyExistsException) e;
-            if (e instanceof MBeanRegistrationException)
-                throw (MBeanRegistrationException) e;
-            if (e instanceof MBeanException)
-                throw (MBeanException) e;
-            if (e instanceof NotCompliantMBeanException)
-                throw (NotCompliantMBeanException) e;
-            if (e instanceof InstanceNotFoundException)
-                throw (InstanceNotFoundException) e;
-            if (e instanceof IOException)
-                throw (IOException) e;
-            throw newIOException("Got unexpected server exception: " + e, e);
-        }
-    }
-
-    public void unregisterMBean(ObjectName name, Subject delegationSubject)
-        throws
-        InstanceNotFoundException,
-        MBeanRegistrationException,
-        IOException {
-        try {
-            final Object params[] = new Object[] { name };
-
-            if (logger.debugOn()) logger.debug("unregisterMBean",
-                 "connectionId=" + connectionId
-                 +", name="+name);
-
-            doPrivilegedOperation(
-              UNREGISTER_MBEAN,
-              params,
-              delegationSubject);
-        } catch (PrivilegedActionException pe) {
-            Exception e = extractException(pe);
-            if (e instanceof InstanceNotFoundException)
-                throw (InstanceNotFoundException) e;
-            if (e instanceof MBeanRegistrationException)
-                throw (MBeanRegistrationException) e;
-            if (e instanceof IOException)
-                throw (IOException) e;
-            throw newIOException("Got unexpected server exception: " + e, e);
-        }
-    }
-
-    public ObjectInstance getObjectInstance(ObjectName name,
-                                            Subject delegationSubject)
-        throws
-        InstanceNotFoundException,
-        IOException {
-
-        checkNonNull("ObjectName", name);
-
-        try {
-            final Object params[] = new Object[] { name };
-
-            if (logger.debugOn()) logger.debug("getObjectInstance",
-                 "connectionId=" + connectionId
-                 +", name="+name);
-
-            return (ObjectInstance)
-                doPrivilegedOperation(
-                  GET_OBJECT_INSTANCE,
-                  params,
-                  delegationSubject);
-        } catch (PrivilegedActionException pe) {
-            Exception e = extractException(pe);
-            if (e instanceof InstanceNotFoundException)
-                throw (InstanceNotFoundException) e;
-            if (e instanceof IOException)
-                throw (IOException) e;
-            throw newIOException("Got unexpected server exception: " + e, e);
-        }
-    }
-
-    @SuppressWarnings("rawtypes")  // MarshalledObject
-    public Set<ObjectInstance>
-        queryMBeans(ObjectName name,
-                    MarshalledObject query,
-                    Subject delegationSubject)
-        throws IOException {
-        final QueryExp queryValue;
-        final boolean debug=logger.debugOn();
-
-        if (debug) logger.debug("queryMBeans",
-                 "connectionId=" + connectionId
-                 +" unwrapping query with defaultClassLoader.");
-
-        queryValue = unwrap(query, defaultContextClassLoader, QueryExp.class, delegationSubject);
-
-        try {
-            final Object params[] = new Object[] { name, queryValue };
-
-            if (debug) logger.debug("queryMBeans",
-                 "connectionId=" + connectionId
-                 +", name="+name +", query="+query);
-
-            return cast(
-                doPrivilegedOperation(
-                  QUERY_MBEANS,
-                  params,
-                  delegationSubject));
-        } catch (PrivilegedActionException pe) {
-            Exception e = extractException(pe);
-            if (e instanceof IOException)
-                throw (IOException) e;
-            throw newIOException("Got unexpected server exception: " + e, e);
-        }
-    }
-
-    @SuppressWarnings("rawtypes")  // MarshalledObject
-    public Set<ObjectName>
-        queryNames(ObjectName name,
-                   MarshalledObject query,
-                   Subject delegationSubject)
-        throws IOException {
-        final QueryExp queryValue;
-        final boolean debug=logger.debugOn();
-
-        if (debug) logger.debug("queryNames",
-                 "connectionId=" + connectionId
-                 +" unwrapping query with defaultClassLoader.");
-
-        queryValue = unwrap(query, defaultContextClassLoader, QueryExp.class, delegationSubject);
-
-        try {
-            final Object params[] = new Object[] { name, queryValue };
-
-            if (debug) logger.debug("queryNames",
-                 "connectionId=" + connectionId
-                 +", name="+name +", query="+query);
-
-            return cast(
-                doPrivilegedOperation(
-                  QUERY_NAMES,
-                  params,
-                  delegationSubject));
-        } catch (PrivilegedActionException pe) {
-            Exception e = extractException(pe);
-            if (e instanceof IOException)
-                throw (IOException) e;
-            throw newIOException("Got unexpected server exception: " + e, e);
-        }
-    }
-
-    public boolean isRegistered(ObjectName name,
-                                Subject delegationSubject) throws IOException {
-        try {
-            final Object params[] = new Object[] { name };
-            return ((Boolean)
-                doPrivilegedOperation(
-                  IS_REGISTERED,
-                  params,
-                  delegationSubject)).booleanValue();
-        } catch (PrivilegedActionException pe) {
-            Exception e = extractException(pe);
-            if (e instanceof IOException)
-                throw (IOException) e;
-            throw newIOException("Got unexpected server exception: " + e, e);
-        }
-    }
-
-    public Integer getMBeanCount(Subject delegationSubject)
-        throws IOException {
-        try {
-            final Object params[] = new Object[] { };
-
-            if (logger.debugOn()) logger.debug("getMBeanCount",
-                 "connectionId=" + connectionId);
-
-            return (Integer)
-                doPrivilegedOperation(
-                  GET_MBEAN_COUNT,
-                  params,
-                  delegationSubject);
-        } catch (PrivilegedActionException pe) {
-            Exception e = extractException(pe);
-            if (e instanceof IOException)
-                throw (IOException) e;
-            throw newIOException("Got unexpected server exception: " + e, e);
-        }
-    }
-
-    public Object getAttribute(ObjectName name,
-                               String attribute,
-                               Subject delegationSubject)
-        throws
-        MBeanException,
-        AttributeNotFoundException,
-        InstanceNotFoundException,
-        ReflectionException,
-        IOException {
-        try {
-            final Object params[] = new Object[] { name, attribute };
-            if (logger.debugOn()) logger.debug("getAttribute",
-                                   "connectionId=" + connectionId
-                                   +", name=" + name
-                                   +", attribute="+ attribute);
-
-            return
-                doPrivilegedOperation(
-                  GET_ATTRIBUTE,
-                  params,
-                  delegationSubject);
-        } catch (PrivilegedActionException pe) {
-            Exception e = extractException(pe);
-            if (e instanceof MBeanException)
-                throw (MBeanException) e;
-            if (e instanceof AttributeNotFoundException)
-                throw (AttributeNotFoundException) e;
-            if (e instanceof InstanceNotFoundException)
-                throw (InstanceNotFoundException) e;
-            if (e instanceof ReflectionException)
-                throw (ReflectionException) e;
-            if (e instanceof IOException)
-                throw (IOException) e;
-            throw newIOException("Got unexpected server exception: " + e, e);
-        }
-    }
-
-    public AttributeList getAttributes(ObjectName name,
-                                       String[] attributes,
-                                       Subject delegationSubject)
-        throws
-        InstanceNotFoundException,
-        ReflectionException,
-        IOException {
-        try {
-            final Object params[] = new Object[] { name, attributes };
-
-            if (logger.debugOn()) logger.debug("getAttributes",
-                                   "connectionId=" + connectionId
-                                   +", name=" + name
-                                   +", attributes="+ strings(attributes));
-
-            return (AttributeList)
-                doPrivilegedOperation(
-                  GET_ATTRIBUTES,
-                  params,
-                  delegationSubject);
-        } catch (PrivilegedActionException pe) {
-            Exception e = extractException(pe);
-            if (e instanceof InstanceNotFoundException)
-                throw (InstanceNotFoundException) e;
-            if (e instanceof ReflectionException)
-                throw (ReflectionException) e;
-            if (e instanceof IOException)
-                throw (IOException) e;
-            throw newIOException("Got unexpected server exception: " + e, e);
-        }
-    }
-
-    @SuppressWarnings("rawtypes")  // MarshalledObject
-    public void setAttribute(ObjectName name,
-                             MarshalledObject attribute,
-                             Subject delegationSubject)
-        throws
-        InstanceNotFoundException,
-        AttributeNotFoundException,
-        InvalidAttributeValueException,
-        MBeanException,
-        ReflectionException,
-        IOException {
-        final Attribute attr;
-        final boolean debug=logger.debugOn();
-
-        if (debug) logger.debug("setAttribute",
-                 "connectionId=" + connectionId
-                 +" unwrapping attribute with MBean extended ClassLoader.");
-
-        attr = unwrap(attribute,
-                      getClassLoaderFor(name),
-                      defaultClassLoader,
-                      Attribute.class, delegationSubject);
-
-        try {
-            final Object params[] = new Object[] { name, attr };
-
-            if (debug) logger.debug("setAttribute",
-                             "connectionId=" + connectionId
-                             +", name="+name
-                             +", attribute name="+attr.getName());
-
-            doPrivilegedOperation(
-              SET_ATTRIBUTE,
-              params,
-              delegationSubject);
-        } catch (PrivilegedActionException pe) {
-            Exception e = extractException(pe);
-            if (e instanceof InstanceNotFoundException)
-                throw (InstanceNotFoundException) e;
-            if (e instanceof AttributeNotFoundException)
-                throw (AttributeNotFoundException) e;
-            if (e instanceof InvalidAttributeValueException)
-                throw (InvalidAttributeValueException) e;
-            if (e instanceof MBeanException)
-                throw (MBeanException) e;
-            if (e instanceof ReflectionException)
-                throw (ReflectionException) e;
-            if (e instanceof IOException)
-                throw (IOException) e;
-            throw newIOException("Got unexpected server exception: " + e, e);
-        }
-    }
-
-    @SuppressWarnings("rawtypes")  // MarshalledObject
-    public AttributeList setAttributes(ObjectName name,
-                         MarshalledObject attributes,
-                         Subject delegationSubject)
-        throws
-        InstanceNotFoundException,
-        ReflectionException,
-        IOException {
-        final AttributeList attrlist;
-        final boolean debug=logger.debugOn();
-
-        if (debug) logger.debug("setAttributes",
-                 "connectionId=" + connectionId
-                 +" unwrapping attributes with MBean extended ClassLoader.");
-
-        attrlist =
-            unwrap(attributes,
-                   getClassLoaderFor(name),
-                   defaultClassLoader,
-                   AttributeList.class, delegationSubject);
-
-        try {
-            final Object params[] = new Object[] { name, attrlist };
-
-            if (debug) logger.debug("setAttributes",
-                             "connectionId=" + connectionId
-                             +", name="+name
-                             +", attribute names="+RMIConnector.getAttributesNames(attrlist));
-
-            return (AttributeList)
-                doPrivilegedOperation(
-                  SET_ATTRIBUTES,
-                  params,
-                  delegationSubject);
-        } catch (PrivilegedActionException pe) {
-            Exception e = extractException(pe);
-            if (e instanceof InstanceNotFoundException)
-                throw (InstanceNotFoundException) e;
-            if (e instanceof ReflectionException)
-                throw (ReflectionException) e;
-            if (e instanceof IOException)
-                throw (IOException) e;
-            throw newIOException("Got unexpected server exception: " + e, e);
-        }
-    }
-
-    @SuppressWarnings("rawtypes")  // MarshalledObject
-    public Object invoke(ObjectName name,
-                         String operationName,
-                         MarshalledObject params,
-                         String signature[],
-                         Subject delegationSubject)
-        throws
-        InstanceNotFoundException,
-        MBeanException,
-        ReflectionException,
-        IOException {
-
-        checkNonNull("ObjectName", name);
-        checkNonNull("Operation name", operationName);
-
-        final Object[] values;
-        final boolean debug=logger.debugOn();
-
-        if (debug) logger.debug("invoke",
-                 "connectionId=" + connectionId
-                 +" unwrapping params with MBean extended ClassLoader.");
-
-        values = nullIsEmpty(unwrap(params,
-                                    getClassLoaderFor(name),
-                                    defaultClassLoader,
-                                    Object[].class, delegationSubject));
-
-        try {
-            final Object params2[] =
-                new Object[] { name, operationName, values,
-                               nullIsEmpty(signature) };
-
-            if (debug) logger.debug("invoke",
-                             "connectionId=" + connectionId
-                             +", name="+name
-                             +", operationName="+operationName
-                             +", signature="+strings(signature));
-
-            return
-                doPrivilegedOperation(
-                  INVOKE,
-                  params2,
-                  delegationSubject);
-        } catch (PrivilegedActionException pe) {
-            Exception e = extractException(pe);
-            if (e instanceof InstanceNotFoundException)
-                throw (InstanceNotFoundException) e;
-            if (e instanceof MBeanException)
-                throw (MBeanException) e;
-            if (e instanceof ReflectionException)
-                throw (ReflectionException) e;
-            if (e instanceof IOException)
-                throw (IOException) e;
-            throw newIOException("Got unexpected server exception: " + e, e);
-        }
-    }
-
-    public String getDefaultDomain(Subject delegationSubject)
-        throws IOException {
-        try {
-            final Object params[] = new Object[] { };
-
-            if (logger.debugOn())  logger.debug("getDefaultDomain",
-                                    "connectionId=" + connectionId);
-
-            return (String)
-                doPrivilegedOperation(
-                  GET_DEFAULT_DOMAIN,
-                  params,
-                  delegationSubject);
-        } catch (PrivilegedActionException pe) {
-            Exception e = extractException(pe);
-            if (e instanceof IOException)
-                throw (IOException) e;
-            throw newIOException("Got unexpected server exception: " + e, e);
-        }
-    }
-
-    public String[] getDomains(Subject delegationSubject) throws IOException {
-        try {
-            final Object params[] = new Object[] { };
-
-            if (logger.debugOn())  logger.debug("getDomains",
-                                    "connectionId=" + connectionId);
-
-            return (String[])
-                doPrivilegedOperation(
-                  GET_DOMAINS,
-                  params,
-                  delegationSubject);
-        } catch (PrivilegedActionException pe) {
-            Exception e = extractException(pe);
-            if (e instanceof IOException)
-                throw (IOException) e;
-            throw newIOException("Got unexpected server exception: " + e, e);
-        }
-    }
-
-    public MBeanInfo getMBeanInfo(ObjectName name, Subject delegationSubject)
-        throws
-        InstanceNotFoundException,
-        IntrospectionException,
-        ReflectionException,
-        IOException {
-
-        checkNonNull("ObjectName", name);
-
-        try {
-            final Object params[] = new Object[] { name };
-
-            if (logger.debugOn())  logger.debug("getMBeanInfo",
-                                    "connectionId=" + connectionId
-                                    +", name="+name);
-
-            return (MBeanInfo)
-                doPrivilegedOperation(
-                  GET_MBEAN_INFO,
-                  params,
-                  delegationSubject);
-        } catch (PrivilegedActionException pe) {
-            Exception e = extractException(pe);
-            if (e instanceof InstanceNotFoundException)
-                throw (InstanceNotFoundException) e;
-            if (e instanceof IntrospectionException)
-                throw (IntrospectionException) e;
-            if (e instanceof ReflectionException)
-                throw (ReflectionException) e;
-            if (e instanceof IOException)
-                throw (IOException) e;
-            throw newIOException("Got unexpected server exception: " + e, e);
-        }
-    }
-
-    public boolean isInstanceOf(ObjectName name,
-                                String className,
-                                Subject delegationSubject)
-        throws InstanceNotFoundException, IOException {
-
-        checkNonNull("ObjectName", name);
-
-        try {
-            final Object params[] = new Object[] { name, className };
-
-            if (logger.debugOn())  logger.debug("isInstanceOf",
-                                    "connectionId=" + connectionId
-                                    +", name="+name
-                                    +", className="+className);
-
-            return ((Boolean)
-                doPrivilegedOperation(
-                  IS_INSTANCE_OF,
-                  params,
-                  delegationSubject)).booleanValue();
-        } catch (PrivilegedActionException pe) {
-            Exception e = extractException(pe);
-            if (e instanceof InstanceNotFoundException)
-                throw (InstanceNotFoundException) e;
-            if (e instanceof IOException)
-                throw (IOException) e;
-            throw newIOException("Got unexpected server exception: " + e, e);
-        }
-    }
-
-    @SuppressWarnings("rawtypes")  // MarshalledObject
-    public Integer[] addNotificationListeners(ObjectName[] names,
-                      MarshalledObject[] filters,
-                      Subject[] delegationSubjects)
-            throws InstanceNotFoundException, IOException {
-
-        if (names == null || filters == null) {
-            throw new IllegalArgumentException("Got null arguments.");
-        }
-
-        Subject[] sbjs = (delegationSubjects != null) ? delegationSubjects :
-        new Subject[names.length];
-        if (names.length != filters.length || filters.length != sbjs.length) {
-            final String msg =
-                "The value lengths of 3 parameters are not same.";
-            throw new IllegalArgumentException(msg);
-        }
-
-        for (int i=0; i<names.length; i++) {
-            if (names[i] == null) {
-                throw new IllegalArgumentException("Null Object name.");
-            }
-        }
-
-        int i=0;
-        ClassLoader targetCl;
-        NotificationFilter[] filterValues =
-            new NotificationFilter[names.length];
-        Integer[] ids = new Integer[names.length];
-        final boolean debug=logger.debugOn();
-
-        try {
-            for (; i<names.length; i++) {
-                targetCl = getClassLoaderFor(names[i]);
-
-                if (debug) logger.debug("addNotificationListener"+
-                                        "(ObjectName,NotificationFilter)",
-                                        "connectionId=" + connectionId +
-                      " unwrapping filter with target extended ClassLoader.");
-
-                filterValues[i] =
-                    unwrap(filters[i], targetCl, defaultClassLoader,
-                           NotificationFilter.class, sbjs[i]);
-
-                if (debug) logger.debug("addNotificationListener"+
-                                        "(ObjectName,NotificationFilter)",
-                                        "connectionId=" + connectionId
-                                        +", name=" + names[i]
-                                        +", filter=" + filterValues[i]);
-
-                ids[i] = (Integer)
-                    doPrivilegedOperation(ADD_NOTIFICATION_LISTENERS,
-                                          new Object[] { names[i],
-                                                         filterValues[i] },
-                                          sbjs[i]);
-            }
-
-            return ids;
-        } catch (Exception e) {
-            // remove all registered listeners
-            for (int j=0; j<i; j++) {
-                try {
-                    getServerNotifFwd().removeNotificationListener(names[j],
-                                                                   ids[j]);
-                } catch (Exception eee) {
-                    // strange
-                }
-            }
-
-            if (e instanceof PrivilegedActionException) {
-                e = extractException(e);
-            }
-
-            if (e instanceof ClassCastException) {
-                throw (ClassCastException) e;
-            } else if (e instanceof IOException) {
-                throw (IOException)e;
-            } else if (e instanceof InstanceNotFoundException) {
-                throw (InstanceNotFoundException) e;
-            } else if (e instanceof RuntimeException) {
-                throw (RuntimeException) e;
-            } else {
-                throw newIOException("Got unexpected server exception: "+e,e);
-            }
-        }
-    }
-
-    @SuppressWarnings("rawtypes")  // MarshalledObject
-    public void addNotificationListener(ObjectName name,
-                       ObjectName listener,
-                       MarshalledObject filter,
-                       MarshalledObject handback,
-                       Subject delegationSubject)
-        throws InstanceNotFoundException, IOException {
-
-        checkNonNull("Target MBean name", name);
-        checkNonNull("Listener MBean name", listener);
-
-        final NotificationFilter filterValue;
-        final Object handbackValue;
-        final boolean debug=logger.debugOn();
-
-        final ClassLoader targetCl = getClassLoaderFor(name);
-
-        if (debug) logger.debug("addNotificationListener"+
-                 "(ObjectName,ObjectName,NotificationFilter,Object)",
-                 "connectionId=" + connectionId
-                 +" unwrapping filter with target extended ClassLoader.");
-
-        filterValue =
-            unwrap(filter, targetCl, defaultClassLoader, NotificationFilter.class, delegationSubject);
-
-        if (debug) logger.debug("addNotificationListener"+
-                 "(ObjectName,ObjectName,NotificationFilter,Object)",
-                 "connectionId=" + connectionId
-                 +" unwrapping handback with target extended ClassLoader.");
-
-        handbackValue =
-            unwrap(handback, targetCl, defaultClassLoader, Object.class, delegationSubject);
-
-        try {
-            final Object params[] =
-                new Object[] { name, listener, filterValue, handbackValue };
-
-            if (debug) logger.debug("addNotificationListener"+
-                 "(ObjectName,ObjectName,NotificationFilter,Object)",
-                             "connectionId=" + connectionId
-                             +", name=" + name
-                             +", listenerName=" + listener
-                             +", filter=" + filterValue
-                             +", handback=" + handbackValue);
-
-            doPrivilegedOperation(
-              ADD_NOTIFICATION_LISTENER_OBJECTNAME,
-              params,
-              delegationSubject);
-        } catch (PrivilegedActionException pe) {
-            Exception e = extractException(pe);
-            if (e instanceof InstanceNotFoundException)
-                throw (InstanceNotFoundException) e;
-            if (e instanceof IOException)
-                throw (IOException) e;
-            throw newIOException("Got unexpected server exception: " + e, e);
-        }
-    }
-
-    public void removeNotificationListeners(ObjectName name,
-                                            Integer[] listenerIDs,
-                                            Subject delegationSubject)
-        throws
-        InstanceNotFoundException,
-        ListenerNotFoundException,
-        IOException {
-
-        if (name == null || listenerIDs == null)
-            throw new IllegalArgumentException("Illegal null parameter");
-
-        for (int i = 0; i < listenerIDs.length; i++) {
-            if (listenerIDs[i] == null)
-                throw new IllegalArgumentException("Null listener ID");
-        }
-
-        try {
-            final Object params[] = new Object[] { name, listenerIDs };
-
-            if (logger.debugOn()) logger.debug("removeNotificationListener"+
-                                   "(ObjectName,Integer[])",
-                                   "connectionId=" + connectionId
-                                   +", name=" + name
-                                   +", listenerIDs=" + objects(listenerIDs));
-
-            doPrivilegedOperation(
-              REMOVE_NOTIFICATION_LISTENER,
-              params,
-              delegationSubject);
-        } catch (PrivilegedActionException pe) {
-            Exception e = extractException(pe);
-            if (e instanceof InstanceNotFoundException)
-                throw (InstanceNotFoundException) e;
-            if (e instanceof ListenerNotFoundException)
-                throw (ListenerNotFoundException) e;
-            if (e instanceof IOException)
-                throw (IOException) e;
-            throw newIOException("Got unexpected server exception: " + e, e);
-        }
-    }
-
-    public void removeNotificationListener(ObjectName name,
-                                           ObjectName listener,
-                                           Subject delegationSubject)
-        throws
-        InstanceNotFoundException,
-        ListenerNotFoundException,
-        IOException {
-
-        checkNonNull("Target MBean name", name);
-        checkNonNull("Listener MBean name", listener);
-
-        try {
-            final Object params[] = new Object[] { name, listener };
-
-            if (logger.debugOn()) logger.debug("removeNotificationListener"+
-                                   "(ObjectName,ObjectName)",
-                                   "connectionId=" + connectionId
-                                   +", name=" + name
-                                   +", listenerName=" + listener);
-
-            doPrivilegedOperation(
-              REMOVE_NOTIFICATION_LISTENER_OBJECTNAME,
-              params,
-              delegationSubject);
-        } catch (PrivilegedActionException pe) {
-            Exception e = extractException(pe);
-            if (e instanceof InstanceNotFoundException)
-                throw (InstanceNotFoundException) e;
-            if (e instanceof ListenerNotFoundException)
-                throw (ListenerNotFoundException) e;
-            if (e instanceof IOException)
-                throw (IOException) e;
-            throw newIOException("Got unexpected server exception: " + e, e);
-        }
-    }
-
-    @SuppressWarnings("rawtypes")  // MarshalledObject
-    public void removeNotificationListener(ObjectName name,
-                        ObjectName listener,
-                        MarshalledObject filter,
-                        MarshalledObject handback,
-                        Subject delegationSubject)
-        throws
-        InstanceNotFoundException,
-        ListenerNotFoundException,
-        IOException {
-
-        checkNonNull("Target MBean name", name);
-        checkNonNull("Listener MBean name", listener);
-
-        final NotificationFilter filterValue;
-        final Object handbackValue;
-        final boolean debug=logger.debugOn();
-
-        final ClassLoader targetCl = getClassLoaderFor(name);
-
-        if (debug) logger.debug("removeNotificationListener"+
-                 "(ObjectName,ObjectName,NotificationFilter,Object)",
-                 "connectionId=" + connectionId
-                 +" unwrapping filter with target extended ClassLoader.");
-
-        filterValue =
-            unwrap(filter, targetCl, defaultClassLoader, NotificationFilter.class, delegationSubject);
-
-        if (debug) logger.debug("removeNotificationListener"+
-                 "(ObjectName,ObjectName,NotificationFilter,Object)",
-                 "connectionId=" + connectionId
-                 +" unwrapping handback with target extended ClassLoader.");
-
-        handbackValue =
-            unwrap(handback, targetCl, defaultClassLoader, Object.class, delegationSubject);
-
-        try {
-            final Object params[] =
-                new Object[] { name, listener, filterValue, handbackValue };
-
-            if (debug) logger.debug("removeNotificationListener"+
-                 "(ObjectName,ObjectName,NotificationFilter,Object)",
-                             "connectionId=" + connectionId
-                             +", name=" + name
-                             +", listenerName=" + listener
-                             +", filter=" + filterValue
-                             +", handback=" + handbackValue);
-
-            doPrivilegedOperation(
-              REMOVE_NOTIFICATION_LISTENER_OBJECTNAME_FILTER_HANDBACK,
-              params,
-              delegationSubject);
-        } catch (PrivilegedActionException pe) {
-            Exception e = extractException(pe);
-            if (e instanceof InstanceNotFoundException)
-                throw (InstanceNotFoundException) e;
-            if (e instanceof ListenerNotFoundException)
-                throw (ListenerNotFoundException) e;
-            if (e instanceof IOException)
-                throw (IOException) e;
-            throw newIOException("Got unexpected server exception: " + e, e);
-        }
-    }
-
-    public NotificationResult fetchNotifications(long clientSequenceNumber,
-                                                 int maxNotifications,
-                                                 long timeout)
-        throws IOException {
-
-        if (logger.debugOn()) logger.debug("fetchNotifications",
-                               "connectionId=" + connectionId
-                               +", timeout=" + timeout);
-
-        if (maxNotifications < 0 || timeout < 0)
-            throw new IllegalArgumentException("Illegal negative argument");
-
-        final boolean serverTerminated =
-            serverCommunicatorAdmin.reqIncoming();
-        try {
-            if (serverTerminated) {
-                // we must not call fetchNotifs() if the server is
-                // terminated (timeout elapsed).
-                // returns null to force the client to stop fetching
-                if (logger.debugOn()) logger.debug("fetchNotifications",
-                               "The notification server has been closed, "
-                                       + "returns null to force the client to stop fetching");
-                return null;
-            }
-            final long csn = clientSequenceNumber;
-            final int mn = maxNotifications;
-            final long t = timeout;
-            PrivilegedAction<NotificationResult> action =
-                new PrivilegedAction<NotificationResult>() {
-                    public NotificationResult run() {
-                        return getServerNotifFwd().fetchNotifs(csn, t, mn);
-                    }
-            };
-            if (acc == null)
-                return action.run();
-            else
-                return AccessController.doPrivileged(action, acc);
-        } finally {
-            serverCommunicatorAdmin.rspOutgoing();
-        }
-    }
-
-    /**
-     * <p>Returns a string representation of this object.  In general,
-     * the <code>toString</code> method returns a string that
-     * "textually represents" this object. The result should be a
-     * concise but informative representation that is easy for a
-     * person to read.</p>
-     *
-     * @return a String representation of this object.
-     **/
-    @Override
-    public String toString() {
-        return super.toString() + ": connectionId=" + connectionId;
-    }
-
-    //------------------------------------------------------------------------
-    // private classes
-    //------------------------------------------------------------------------
-
-    private class PrivilegedOperation
-            implements PrivilegedExceptionAction<Object> {
-
-        public PrivilegedOperation(int operation, Object[] params) {
-            this.operation = operation;
-            this.params = params;
-        }
-
-        public Object run() throws Exception {
-            return doOperation(operation, params);
-        }
-
-        private int operation;
-        private Object[] params;
-    }
-
-    //------------------------------------------------------------------------
-    // private classes
-    //------------------------------------------------------------------------
-    private class RMIServerCommunicatorAdmin extends ServerCommunicatorAdmin {
-        public RMIServerCommunicatorAdmin(long timeout) {
-            super(timeout);
-        }
-
-        protected void doStop() {
-            try {
-                close();
-            } catch (IOException ie) {
-                logger.warning("RMIServerCommunicatorAdmin-doStop",
-                               "Failed to close: " + ie);
-                logger.debug("RMIServerCommunicatorAdmin-doStop",ie);
-            }
-        }
-
-    }
-
-
-    //------------------------------------------------------------------------
-    // private methods
-    //------------------------------------------------------------------------
-
-    private ClassLoader getClassLoader(final ObjectName name)
-        throws InstanceNotFoundException {
-        try {
-            return
-                AccessController.doPrivileged(
-                    new PrivilegedExceptionAction<ClassLoader>() {
-                        public ClassLoader run() throws InstanceNotFoundException {
-                            return mbeanServer.getClassLoader(name);
-                        }
-                    },
-                    withPermissions(new MBeanPermission("*", "getClassLoader"))
-            );
-        } catch (PrivilegedActionException pe) {
-            throw (InstanceNotFoundException) extractException(pe);
-        }
-    }
-
-    private ClassLoader getClassLoaderFor(final ObjectName name)
-        throws InstanceNotFoundException {
-        try {
-            return (ClassLoader)
-                AccessController.doPrivileged(
-                    new PrivilegedExceptionAction<Object>() {
-                        public Object run() throws InstanceNotFoundException {
-                            return mbeanServer.getClassLoaderFor(name);
-                        }
-                    },
-                    withPermissions(new MBeanPermission("*", "getClassLoaderFor"))
-            );
-        } catch (PrivilegedActionException pe) {
-            throw (InstanceNotFoundException) extractException(pe);
-        }
-    }
-
-    private Object doPrivilegedOperation(final int operation,
-                                         final Object[] params,
-                                         final Subject delegationSubject)
-        throws PrivilegedActionException, IOException {
-
-        serverCommunicatorAdmin.reqIncoming();
-        try {
-
-            final AccessControlContext reqACC;
-            if (delegationSubject == null)
-                reqACC = acc;
-            else {
-                if (subject == null) {
-                    final String msg =
-                        "Subject delegation cannot be enabled unless " +
-                        "an authenticated subject is put in place";
-                    throw new SecurityException(msg);
-                }
-                reqACC = subjectDelegator.delegatedContext(
-                    acc, delegationSubject, removeCallerContext);
-            }
-
-            PrivilegedOperation op =
-                new PrivilegedOperation(operation, params);
-            if (reqACC == null) {
-                try {
-                    return op.run();
-                } catch (Exception e) {
-                    if (e instanceof RuntimeException)
-                        throw (RuntimeException) e;
-                    throw new PrivilegedActionException(e);
-                }
-            } else {
-                return AccessController.doPrivileged(op, reqACC);
-            }
-        } catch (Error e) {
-            throw new JMXServerErrorException(e.toString(),e);
-        } finally {
-            serverCommunicatorAdmin.rspOutgoing();
-        }
-    }
-
-    private Object doOperation(int operation, Object[] params)
-        throws Exception {
-
-        switch (operation) {
-
-        case CREATE_MBEAN:
-            return mbeanServer.createMBean((String)params[0],
-                                           (ObjectName)params[1]);
-
-        case CREATE_MBEAN_LOADER:
-            return mbeanServer.createMBean((String)params[0],
-                                           (ObjectName)params[1],
-                                           (ObjectName)params[2]);
-
-        case CREATE_MBEAN_PARAMS:
-            return mbeanServer.createMBean((String)params[0],
-                                           (ObjectName)params[1],
-                                           (Object[])params[2],
-                                           (String[])params[3]);
-
-        case CREATE_MBEAN_LOADER_PARAMS:
-            return mbeanServer.createMBean((String)params[0],
-                                           (ObjectName)params[1],
-                                           (ObjectName)params[2],
-                                           (Object[])params[3],
-                                           (String[])params[4]);
-
-        case GET_ATTRIBUTE:
-            return mbeanServer.getAttribute((ObjectName)params[0],
-                                            (String)params[1]);
-
-        case GET_ATTRIBUTES:
-            return mbeanServer.getAttributes((ObjectName)params[0],
-                                             (String[])params[1]);
-
-        case GET_DEFAULT_DOMAIN:
-            return mbeanServer.getDefaultDomain();
-
-        case GET_DOMAINS:
-            return mbeanServer.getDomains();
-
-        case GET_MBEAN_COUNT:
-            return mbeanServer.getMBeanCount();
-
-        case GET_MBEAN_INFO:
-            return mbeanServer.getMBeanInfo((ObjectName)params[0]);
-
-        case GET_OBJECT_INSTANCE:
-            return mbeanServer.getObjectInstance((ObjectName)params[0]);
-
-        case INVOKE:
-            return mbeanServer.invoke((ObjectName)params[0],
-                                      (String)params[1],
-                                      (Object[])params[2],
-                                      (String[])params[3]);
-
-        case IS_INSTANCE_OF:
-            return mbeanServer.isInstanceOf((ObjectName)params[0],
-                                            (String)params[1])
-                ? Boolean.TRUE : Boolean.FALSE;
-
-        case IS_REGISTERED:
-            return mbeanServer.isRegistered((ObjectName)params[0])
-                ? Boolean.TRUE : Boolean.FALSE;
-
-        case QUERY_MBEANS:
-            return mbeanServer.queryMBeans((ObjectName)params[0],
-                                           (QueryExp)params[1]);
-
-        case QUERY_NAMES:
-            return mbeanServer.queryNames((ObjectName)params[0],
-                                          (QueryExp)params[1]);
-
-        case SET_ATTRIBUTE:
-            mbeanServer.setAttribute((ObjectName)params[0],
-                                     (Attribute)params[1]);
-            return null;
-
-        case SET_ATTRIBUTES:
-            return mbeanServer.setAttributes((ObjectName)params[0],
-                                             (AttributeList)params[1]);
-
-        case UNREGISTER_MBEAN:
-            mbeanServer.unregisterMBean((ObjectName)params[0]);
-            return null;
-
-        case ADD_NOTIFICATION_LISTENERS:
-            return getServerNotifFwd().addNotificationListener(
-                                                (ObjectName)params[0],
-                                                (NotificationFilter)params[1]);
-
-        case ADD_NOTIFICATION_LISTENER_OBJECTNAME:
-            mbeanServer.addNotificationListener((ObjectName)params[0],
-                                                (ObjectName)params[1],
-                                                (NotificationFilter)params[2],
-                                                params[3]);
-            return null;
-
-        case REMOVE_NOTIFICATION_LISTENER:
-            getServerNotifFwd().removeNotificationListener(
-                                                   (ObjectName)params[0],
-                                                   (Integer[])params[1]);
-            return null;
-
-        case REMOVE_NOTIFICATION_LISTENER_OBJECTNAME:
-            mbeanServer.removeNotificationListener((ObjectName)params[0],
-                                                   (ObjectName)params[1]);
-            return null;
-
-        case REMOVE_NOTIFICATION_LISTENER_OBJECTNAME_FILTER_HANDBACK:
-            mbeanServer.removeNotificationListener(
-                                          (ObjectName)params[0],
-                                          (ObjectName)params[1],
-                                          (NotificationFilter)params[2],
-                                          params[3]);
-            return null;
-
-        default:
-            throw new IllegalArgumentException("Invalid operation");
-        }
-    }
-
-    private static class SetCcl implements PrivilegedExceptionAction<ClassLoader> {
-        private final ClassLoader classLoader;
-
-        SetCcl(ClassLoader classLoader) {
-            this.classLoader = classLoader;
-        }
-
-        public ClassLoader run() {
-            Thread currentThread = Thread.currentThread();
-            ClassLoader old = currentThread.getContextClassLoader();
-            currentThread.setContextClassLoader(classLoader);
-            return old;
-        }
-    }
-
-    private <T> T unwrap(final MarshalledObject<?> mo,
-                                final ClassLoader cl,
-                                final Class<T> wrappedClass,
-                                Subject delegationSubject)
-            throws IOException {
-        if (mo == null) {
-            return null;
-        }
-        try {
-            final ClassLoader old = AccessController.doPrivileged(new SetCcl(cl));
-            try{
-                final AccessControlContext reqACC;
-                if (delegationSubject == null)
-                    reqACC = acc;
-                else {
-                    if (subject == null) {
-                        final String msg =
-                            "Subject delegation cannot be enabled unless " +
-                            "an authenticated subject is put in place";
-                        throw new SecurityException(msg);
-                    }
-                    reqACC = subjectDelegator.delegatedContext(
-                        acc, delegationSubject, removeCallerContext);
-                }
-                if(reqACC != null){
-                    return AccessController.doPrivileged(
-                            (PrivilegedExceptionAction<T>) () ->
-                                    wrappedClass.cast(mo.get()), reqACC);
-                }else{
-                    return wrappedClass.cast(mo.get());
-                }
-            }finally{
-                AccessController.doPrivileged(new SetCcl(old));
-            }
-        } catch (PrivilegedActionException pe) {
-            Exception e = extractException(pe);
-            if (e instanceof IOException) {
-                throw (IOException) e;
-            }
-            if (e instanceof ClassNotFoundException) {
-                throw new UnmarshalException(e.toString(), e);
-            }
-            logger.warning("unwrap", "Failed to unmarshall object: " + e);
-            logger.debug("unwrap", e);
-        }catch (ClassNotFoundException ex) {
-            logger.warning("unwrap", "Failed to unmarshall object: " + ex);
-            logger.debug("unwrap", ex);
-            throw new UnmarshalException(ex.toString(), ex);
-        }
-        return null;
-    }
-
-    private <T> T unwrap(final MarshalledObject<?> mo,
-                                final ClassLoader cl1,
-                                final ClassLoader cl2,
-                                final Class<T> wrappedClass,
-                                Subject delegationSubject)
-        throws IOException {
-        if (mo == null) {
-            return null;
-        }
-        try {
-            ClassLoader orderCL = AccessController.doPrivileged(
-                new PrivilegedExceptionAction<ClassLoader>() {
-                    public ClassLoader run() throws Exception {
-                        return new CombinedClassLoader(Thread.currentThread().getContextClassLoader(),
-                                new OrderClassLoaders(cl1, cl2));
-                    }
-                }
-            );
-            return unwrap(mo, orderCL, wrappedClass,delegationSubject);
-        } catch (PrivilegedActionException pe) {
-            Exception e = extractException(pe);
-            if (e instanceof IOException) {
-                throw (IOException) e;
-            }
-            if (e instanceof ClassNotFoundException) {
-                throw new UnmarshalException(e.toString(), e);
-            }
-            logger.warning("unwrap", "Failed to unmarshall object: " + e);
-            logger.debug("unwrap", e);
-        }
-        return null;
-    }
-
-    /**
-     * Construct a new IOException with a nested exception.
-     * The nested exception is set only if JDK {@literal >= 1.4}
-     */
-    private static IOException newIOException(String message,
-                                              Throwable cause) {
-        final IOException x = new IOException(message);
-        return EnvHelp.initCause(x,cause);
-    }
-
-    /**
-     * Iterate until we extract the real exception
-     * from a stack of PrivilegedActionExceptions.
-     */
-    private static Exception extractException(Exception e) {
-        while (e instanceof PrivilegedActionException) {
-            e = ((PrivilegedActionException)e).getException();
-        }
-        return e;
-    }
-
-    private static final Object[] NO_OBJECTS = new Object[0];
-    private static final String[] NO_STRINGS = new String[0];
-
-    /*
-     * The JMX spec doesn't explicitly say that a null Object[] or
-     * String[] in e.g. MBeanServer.invoke is equivalent to an empty
-     * array, but the RI behaves that way.  In the interests of
-     * maximal interoperability, we make it so even when we're
-     * connected to some other JMX implementation that might not do
-     * that.  This should be clarified in the next version of JMX.
-     */
-    private static Object[] nullIsEmpty(Object[] array) {
-        return (array == null) ? NO_OBJECTS : array;
-    }
-
-    private static String[] nullIsEmpty(String[] array) {
-        return (array == null) ? NO_STRINGS : array;
-    }
-
-    /*
-     * Similarly, the JMX spec says for some but not all methods in
-     * MBeanServer that take an ObjectName target, that if it's null
-     * you get this exception.  We specify it for all of them, and
-     * make it so for the ones where it's not specified in JMX even if
-     * the JMX implementation doesn't do so.
-     */
-    private static void checkNonNull(String what, Object x) {
-        if (x == null) {
-            RuntimeException wrapped =
-                new IllegalArgumentException(what + " must not be null");
-            throw new RuntimeOperationsException(wrapped);
-        }
-    }
-
-    //------------------------------------------------------------------------
-    // private variables
-    //------------------------------------------------------------------------
-
-    private final Subject subject;
-
-    private final SubjectDelegator subjectDelegator;
-
-    private final boolean removeCallerContext;
-
-    private final AccessControlContext acc;
-
-    private final RMIServerImpl rmiServer;
-
-    private final MBeanServer mbeanServer;
-
-    private final ClassLoader defaultClassLoader;
-
-    private final ClassLoader defaultContextClassLoader;
-
-    private final ClassLoaderWithRepository classLoaderWithRepository;
-
-    private boolean terminated = false;
-
-    private final String connectionId;
-
-    private final ServerCommunicatorAdmin serverCommunicatorAdmin;
-
-    // Method IDs for doOperation
-    //---------------------------
-
-    private final static int
-        ADD_NOTIFICATION_LISTENERS                              = 1;
-    private final static int
-        ADD_NOTIFICATION_LISTENER_OBJECTNAME                    = 2;
-    private final static int
-        CREATE_MBEAN                                            = 3;
-    private final static int
-        CREATE_MBEAN_PARAMS                                     = 4;
-    private final static int
-        CREATE_MBEAN_LOADER                                     = 5;
-    private final static int
-        CREATE_MBEAN_LOADER_PARAMS                              = 6;
-    private final static int
-        GET_ATTRIBUTE                                           = 7;
-    private final static int
-        GET_ATTRIBUTES                                          = 8;
-    private final static int
-        GET_DEFAULT_DOMAIN                                      = 9;
-    private final static int
-        GET_DOMAINS                                             = 10;
-    private final static int
-        GET_MBEAN_COUNT                                         = 11;
-    private final static int
-        GET_MBEAN_INFO                                          = 12;
-    private final static int
-        GET_OBJECT_INSTANCE                                     = 13;
-    private final static int
-        INVOKE                                                  = 14;
-    private final static int
-        IS_INSTANCE_OF                                          = 15;
-    private final static int
-        IS_REGISTERED                                           = 16;
-    private final static int
-        QUERY_MBEANS                                            = 17;
-    private final static int
-        QUERY_NAMES                                             = 18;
-    private final static int
-        REMOVE_NOTIFICATION_LISTENER                            = 19;
-    private final static int
-        REMOVE_NOTIFICATION_LISTENER_OBJECTNAME                 = 20;
-    private final static int
-        REMOVE_NOTIFICATION_LISTENER_OBJECTNAME_FILTER_HANDBACK = 21;
-    private final static int
-        SET_ATTRIBUTE                                           = 22;
-    private final static int
-        SET_ATTRIBUTES                                          = 23;
-    private final static int
-        UNREGISTER_MBEAN                                        = 24;
-
-    // SERVER NOTIFICATION
-    //--------------------
-
-    private ServerNotifForwarder serverNotifForwarder;
-    private Map<String, ?> env;
-
-    // TRACES & DEBUG
-    //---------------
-
-    private static String objects(final Object[] objs) {
-        if (objs == null)
-            return "null";
-        else
-            return Arrays.asList(objs).toString();
-    }
-
-    private static String strings(final String[] strs) {
-        return objects(strs);
-    }
-
-    private static final ClassLogger logger =
-        new ClassLogger("javax.management.remote.rmi", "RMIConnectionImpl");
-
-    private static final class CombinedClassLoader extends ClassLoader {
-
-        private final static class ClassLoaderWrapper extends ClassLoader {
-            ClassLoaderWrapper(ClassLoader cl) {
-                super(cl);
-            }
-
-            @Override
-            protected Class<?> loadClass(String name, boolean resolve)
-                    throws ClassNotFoundException {
-                return super.loadClass(name, resolve);
-            }
-        };
-
-        final ClassLoaderWrapper defaultCL;
-
-        private CombinedClassLoader(ClassLoader parent, ClassLoader defaultCL) {
-            super(parent);
-            this.defaultCL = new ClassLoaderWrapper(defaultCL);
-        }
-
-        @Override
-        protected Class<?> loadClass(String name, boolean resolve)
-        throws ClassNotFoundException {
-            ReflectUtil.checkPackageAccess(name);
-            try {
-                super.loadClass(name, resolve);
-            } catch(Exception e) {
-                for(Throwable t = e; t != null; t = t.getCause()) {
-                    if(t instanceof SecurityException) {
-                        throw t==e?(SecurityException)t:new SecurityException(t.getMessage(), e);
-                    }
-                }
-            }
-            final Class<?> cl = defaultCL.loadClass(name, resolve);
-            return cl;
-        }
-
-    }
-}
--- a/jdk/src/java.management/share/classes/javax/management/remote/rmi/RMIConnector.java	Thu Feb 02 12:28:23 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2289 +0,0 @@
-/*
- * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package javax.management.remote.rmi;
-
-import com.sun.jmx.mbeanserver.Util;
-import com.sun.jmx.remote.internal.ClientCommunicatorAdmin;
-import com.sun.jmx.remote.internal.ClientListenerInfo;
-import com.sun.jmx.remote.internal.ClientNotifForwarder;
-import com.sun.jmx.remote.internal.ProxyRef;
-import com.sun.jmx.remote.util.ClassLogger;
-import com.sun.jmx.remote.util.EnvHelp;
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InvalidObjectException;
-import java.io.ObjectInputStream;
-import java.io.ObjectStreamClass;
-import java.io.Serializable;
-import java.lang.ref.WeakReference;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Module;
-import java.lang.reflect.Proxy;
-import java.net.MalformedURLException;
-import java.rmi.MarshalledObject;
-import java.rmi.NoSuchObjectException;
-import java.rmi.Remote;
-import java.rmi.ServerException;
-import java.rmi.UnmarshalException;
-import java.rmi.server.RMIClientSocketFactory;
-import java.rmi.server.RemoteObject;
-import java.rmi.server.RemoteObjectInvocationHandler;
-import java.rmi.server.RemoteRef;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import java.security.PrivilegedExceptionAction;
-import java.security.ProtectionDomain;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Hashtable;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-import java.util.WeakHashMap;
-import java.util.stream.Collectors;
-import javax.management.Attribute;
-import javax.management.AttributeList;
-import javax.management.AttributeNotFoundException;
-import javax.management.InstanceAlreadyExistsException;
-import javax.management.InstanceNotFoundException;
-import javax.management.IntrospectionException;
-import javax.management.InvalidAttributeValueException;
-import javax.management.ListenerNotFoundException;
-import javax.management.MBeanException;
-import javax.management.MBeanInfo;
-import javax.management.MBeanRegistrationException;
-import javax.management.MBeanServerConnection;
-import javax.management.MBeanServerDelegate;
-import javax.management.MBeanServerNotification;
-import javax.management.NotCompliantMBeanException;
-import javax.management.Notification;
-import javax.management.NotificationBroadcasterSupport;
-import javax.management.NotificationFilter;
-import javax.management.NotificationFilterSupport;
-import javax.management.NotificationListener;
-import javax.management.ObjectInstance;
-import javax.management.ObjectName;
-import javax.management.QueryExp;
-import javax.management.ReflectionException;
-import javax.management.remote.JMXConnectionNotification;
-import javax.management.remote.JMXConnector;
-import javax.management.remote.JMXConnectorFactory;
-import javax.management.remote.JMXServiceURL;
-import javax.management.remote.NotificationResult;
-import javax.management.remote.JMXAddressable;
-import javax.naming.InitialContext;
-import javax.naming.NamingException;
-import javax.rmi.ssl.SslRMIClientSocketFactory;
-import javax.security.auth.Subject;
-import jdk.internal.module.Modules;
-import sun.reflect.misc.ReflectUtil;
-import sun.rmi.server.UnicastRef2;
-import sun.rmi.transport.LiveRef;
-
-/**
- * <p>A connection to a remote RMI connector.  Usually, such
- * connections are made using {@link
- * javax.management.remote.JMXConnectorFactory JMXConnectorFactory}.
- * However, specialized applications can use this class directly, for
- * example with an {@link RMIServer} stub obtained without going
- * through JNDI.</p>
- *
- * @since 1.5
- */
-public class RMIConnector implements JMXConnector, Serializable, JMXAddressable {
-
-    private static final ClassLogger logger =
-            new ClassLogger("javax.management.remote.rmi", "RMIConnector");
-
-    private static final long serialVersionUID = 817323035842634473L;
-
-    private RMIConnector(RMIServer rmiServer, JMXServiceURL address,
-            Map<String, ?> environment) {
-        if (rmiServer == null && address == null) throw new
-                IllegalArgumentException("rmiServer and jmxServiceURL both null");
-        initTransients();
-
-        this.rmiServer = rmiServer;
-        this.jmxServiceURL = address;
-        if (environment == null) {
-            this.env = Collections.emptyMap();
-        } else {
-            EnvHelp.checkAttributes(environment);
-            this.env = Collections.unmodifiableMap(environment);
-        }
-    }
-
-    /**
-     * <p>Constructs an {@code RMIConnector} that will connect
-     * the RMI connector server with the given address.</p>
-     *
-     * <p>The address can refer directly to the connector server,
-     * using the following syntax:</p>
-     *
-     * <pre>
-     * service:jmx:rmi://<em>[host[:port]]</em>/stub/<em>encoded-stub</em>
-     * </pre>
-     *
-     * <p>(Here, the square brackets {@code []} are not part of the
-     * address but indicate that the host and port are optional.)</p>
-     *
-     * <p>The address can instead indicate where to find an RMI stub
-     * through JNDI, using the following syntax:</p>
-     *
-     * <pre>
-     * service:jmx:rmi://<em>[host[:port]]</em>/jndi/<em>jndi-name</em>
-     * </pre>
-     *
-     * <p>An implementation may also recognize additional address
-     * syntaxes, for example:</p>
-     *
-     * <pre>
-     * service:jmx:iiop://<em>[host[:port]]</em>/stub/<em>encoded-stub</em>
-     * </pre>
-     *
-     * @param url the address of the RMI connector server.
-     *
-     * @param environment additional attributes specifying how to make
-     * the connection.  For JNDI-based addresses, these attributes can
-     * usefully include JNDI attributes recognized by {@link
-     * InitialContext#InitialContext(Hashtable) InitialContext}.  This
-     * parameter can be null, which is equivalent to an empty Map.
-     *
-     * @exception IllegalArgumentException if {@code url}
-     * is null.
-     */
-    public RMIConnector(JMXServiceURL url, Map<String,?> environment) {
-        this(null, url, environment);
-    }
-
-    /**
-     * <p>Constructs an {@code RMIConnector} using the given RMI stub.
-     *
-     * @param rmiServer an RMI stub representing the RMI connector server.
-     * @param environment additional attributes specifying how to make
-     * the connection.  This parameter can be null, which is
-     * equivalent to an empty Map.
-     *
-     * @exception IllegalArgumentException if {@code rmiServer}
-     * is null.
-     */
-    public RMIConnector(RMIServer rmiServer, Map<String,?> environment) {
-        this(rmiServer, null, environment);
-    }
-
-    /**
-     * <p>Returns a string representation of this object.  In general,
-     * the {@code toString} method returns a string that
-     * "textually represents" this object. The result should be a
-     * concise but informative representation that is easy for a
-     * person to read.</p>
-     *
-     * @return a String representation of this object.
-     **/
-    @Override
-    public String toString() {
-        final StringBuilder b = new StringBuilder(this.getClass().getName());
-        b.append(":");
-        if (rmiServer != null) {
-            b.append(" rmiServer=").append(rmiServer.toString());
-        }
-        if (jmxServiceURL != null) {
-            if (rmiServer!=null) b.append(",");
-            b.append(" jmxServiceURL=").append(jmxServiceURL.toString());
-        }
-        return b.toString();
-    }
-
-    /**
-     * <p>The address of this connector.</p>
-     *
-     * @return the address of this connector, or null if it
-     * does not have one.
-     *
-     * @since 1.6
-     */
-    public JMXServiceURL getAddress() {
-        return jmxServiceURL;
-    }
-
-    //--------------------------------------------------------------------
-    // implements JMXConnector interface
-    //--------------------------------------------------------------------
-
-    /**
-     * @throws IOException if the connection could not be made because of a
-     *   communication problem
-     */
-    public void connect() throws IOException {
-        connect(null);
-    }
-
-    /**
-     * @throws IOException if the connection could not be made because of a
-     *   communication problem
-     */
-    public synchronized void connect(Map<String,?> environment)
-    throws IOException {
-        final boolean tracing = logger.traceOn();
-        String        idstr   = (tracing?"["+this.toString()+"]":null);
-
-        if (terminated) {
-            logger.trace("connect",idstr + " already closed.");
-            throw new IOException("Connector closed");
-        }
-        if (connected) {
-            logger.trace("connect",idstr + " already connected.");
-            return;
-        }
-
-        try {
-            if (tracing) logger.trace("connect",idstr + " connecting...");
-
-            final Map<String, Object> usemap =
-                    new HashMap<String, Object>((this.env==null) ?
-                        Collections.<String, Object>emptyMap() : this.env);
-
-
-            if (environment != null) {
-                EnvHelp.checkAttributes(environment);
-                usemap.putAll(environment);
-            }
-
-            // Get RMIServer stub from directory or URL encoding if needed.
-            if (tracing) logger.trace("connect",idstr + " finding stub...");
-            RMIServer stub = (rmiServer!=null)?rmiServer:
-                findRMIServer(jmxServiceURL, usemap);
-
-            // Check for secure RMIServer stub if the corresponding
-            // client-side environment property is set to "true".
-            //
-            String stringBoolean =  (String) usemap.get("jmx.remote.x.check.stub");
-            boolean checkStub = EnvHelp.computeBooleanFromString(stringBoolean);
-
-            if (checkStub) checkStub(stub, rmiServerImplStubClass);
-
-            if (tracing) logger.trace("connect",idstr + " connecting stub...");
-            idstr = (tracing?"["+this.toString()+"]":null);
-
-            // Calling newClient on the RMIServer stub.
-            if (tracing)
-                logger.trace("connect",idstr + " getting connection...");
-            Object credentials = usemap.get(CREDENTIALS);
-
-            try {
-                connection = getConnection(stub, credentials, checkStub);
-            } catch (java.rmi.RemoteException re) {
-                throw re;
-            }
-
-            // Always use one of:
-            //   ClassLoader provided in Map at connect time,
-            //   or contextClassLoader at connect time.
-            if (tracing)
-                logger.trace("connect",idstr + " getting class loader...");
-            defaultClassLoader = EnvHelp.resolveClientClassLoader(usemap);
-
-            usemap.put(JMXConnectorFactory.DEFAULT_CLASS_LOADER,
-                    defaultClassLoader);
-
-            rmiNotifClient = new RMINotifClient(defaultClassLoader, usemap);
-
-            env = usemap;
-            final long checkPeriod = EnvHelp.getConnectionCheckPeriod(usemap);
-            communicatorAdmin = new RMIClientCommunicatorAdmin(checkPeriod);
-
-            connected = true;
-
-            // The connectionId variable is used in doStart(), when
-            // reconnecting, to identify the "old" connection.
-            //
-            connectionId = getConnectionId();
-
-            Notification connectedNotif =
-                    new JMXConnectionNotification(JMXConnectionNotification.OPENED,
-                    this,
-                    connectionId,
-                    clientNotifSeqNo++,
-                    "Successful connection",
-                    null);
-            sendNotification(connectedNotif);
-
-            if (tracing) logger.trace("connect",idstr + " done...");
-        } catch (IOException e) {
-            if (tracing)
-                logger.trace("connect",idstr + " failed to connect: " + e);
-            throw e;
-        } catch (RuntimeException e) {
-            if (tracing)
-                logger.trace("connect",idstr + " failed to connect: " + e);
-            throw e;
-        } catch (NamingException e) {
-            final String msg = "Failed to retrieve RMIServer stub: " + e;
-            if (tracing) logger.trace("connect",idstr + " " + msg);
-            throw EnvHelp.initCause(new IOException(msg),e);
-        }
-    }
-
-    public synchronized String getConnectionId() throws IOException {
-        if (terminated || !connected) {
-            if (logger.traceOn())
-                logger.trace("getConnectionId","["+this.toString()+
-                        "] not connected.");
-
-            throw new IOException("Not connected");
-        }
-
-        // we do a remote call to have an IOException if the connection is broken.
-        // see the bug 4939578
-        return connection.getConnectionId();
-    }
-
-    public synchronized MBeanServerConnection getMBeanServerConnection()
-    throws IOException {
-        return getMBeanServerConnection(null);
-    }
-
-    public synchronized MBeanServerConnection
-            getMBeanServerConnection(Subject delegationSubject)
-            throws IOException {
-
-        if (terminated) {
-            if (logger.traceOn())
-                logger.trace("getMBeanServerConnection","[" + this.toString() +
-                        "] already closed.");
-            throw new IOException("Connection closed");
-        } else if (!connected) {
-            if (logger.traceOn())
-                logger.trace("getMBeanServerConnection","[" + this.toString() +
-                        "] is not connected.");
-            throw new IOException("Not connected");
-        }
-
-        return getConnectionWithSubject(delegationSubject);
-    }
-
-    public void
-            addConnectionNotificationListener(NotificationListener listener,
-            NotificationFilter filter,
-            Object handback) {
-        if (listener == null)
-            throw new NullPointerException("listener");
-        connectionBroadcaster.addNotificationListener(listener, filter,
-                handback);
-    }
-
-    public void
-            removeConnectionNotificationListener(NotificationListener listener)
-            throws ListenerNotFoundException {
-        if (listener == null)
-            throw new NullPointerException("listener");
-        connectionBroadcaster.removeNotificationListener(listener);
-    }
-
-    public void
-            removeConnectionNotificationListener(NotificationListener listener,
-            NotificationFilter filter,
-            Object handback)
-            throws ListenerNotFoundException {
-        if (listener == null)
-            throw new NullPointerException("listener");
-        connectionBroadcaster.removeNotificationListener(listener, filter,
-                handback);
-    }
-
-    private void sendNotification(Notification n) {
-        connectionBroadcaster.sendNotification(n);
-    }
-
-    public synchronized void close() throws IOException {
-        close(false);
-    }
-
-    // allows to do close after setting the flag "terminated" to true.
-    // It is necessary to avoid a deadlock, see 6296324
-    private synchronized void close(boolean intern) throws IOException {
-        final boolean tracing = logger.traceOn();
-        final boolean debug   = logger.debugOn();
-        final String  idstr   = (tracing?"["+this.toString()+"]":null);
-
-        if (!intern) {
-            // Return if already cleanly closed.
-            //
-            if (terminated) {
-                if (closeException == null) {
-                    if (tracing) logger.trace("close",idstr + " already closed.");
-                    return;
-                }
-            } else {
-                terminated = true;
-            }
-        }
-
-        if (closeException != null && tracing) {
-            // Already closed, but not cleanly. Attempt again.
-            //
-            if (tracing) {
-                logger.trace("close",idstr + " had failed: " + closeException);
-                logger.trace("close",idstr + " attempting to close again.");
-            }
-        }
-
-        String savedConnectionId = null;
-        if (connected) {
-            savedConnectionId = connectionId;
-        }
-
-        closeException = null;
-
-        if (tracing) logger.trace("close",idstr + " closing.");
-
-        if (communicatorAdmin != null) {
-            communicatorAdmin.terminate();
-        }
-
-        if (rmiNotifClient != null) {
-            try {
-                rmiNotifClient.terminate();
-                if (tracing) logger.trace("close",idstr +
-                        " RMI Notification client terminated.");
-            } catch (RuntimeException x) {
-                closeException = x;
-                if (tracing) logger.trace("close",idstr +
-                        " Failed to terminate RMI Notification client: " + x);
-                if (debug) logger.debug("close",x);
-            }
-        }
-
-        if (connection != null) {
-            try {
-                connection.close();
-                if (tracing) logger.trace("close",idstr + " closed.");
-            } catch (NoSuchObjectException nse) {
-                // OK, the server maybe closed itself.
-            } catch (IOException e) {
-                closeException = e;
-                if (tracing) logger.trace("close",idstr +
-                        " Failed to close RMIServer: " + e);
-                if (debug) logger.debug("close",e);
-            }
-        }
-
-        // Clean up MBeanServerConnection table
-        //
-        rmbscMap.clear();
-
-        /* Send notification of closure.  We don't do this if the user
-         * never called connect() on the connector, because there's no
-         * connection id in that case.  */
-
-        if (savedConnectionId != null) {
-            Notification closedNotif =
-                    new JMXConnectionNotification(JMXConnectionNotification.CLOSED,
-                    this,
-                    savedConnectionId,
-                    clientNotifSeqNo++,
-                    "Client has been closed",
-                    null);
-            sendNotification(closedNotif);
-        }
-
-        // throw exception if needed
-        //
-        if (closeException != null) {
-            if (tracing) logger.trace("close",idstr + " failed to close: " +
-                    closeException);
-            if (closeException instanceof IOException)
-                throw (IOException) closeException;
-            if (closeException instanceof RuntimeException)
-                throw (RuntimeException) closeException;
-            final IOException x =
-                    new IOException("Failed to close: " + closeException);
-            throw EnvHelp.initCause(x,closeException);
-        }
-    }
-
-    // added for re-connection
-    private Integer addListenerWithSubject(ObjectName name,
-                                           MarshalledObject<NotificationFilter> filter,
-                                           Subject delegationSubject,
-                                           boolean reconnect)
-        throws InstanceNotFoundException, IOException {
-
-        final boolean debug = logger.debugOn();
-        if (debug)
-            logger.debug("addListenerWithSubject",
-                    "(ObjectName,MarshalledObject,Subject)");
-
-        final ObjectName[] names = new ObjectName[] {name};
-        final MarshalledObject<NotificationFilter>[] filters =
-                Util.cast(new MarshalledObject<?>[] {filter});
-        final Subject[] delegationSubjects = new Subject[] {
-            delegationSubject
-        };
-
-        final Integer[] listenerIDs =
-                addListenersWithSubjects(names,filters,delegationSubjects,
-                reconnect);
-
-        if (debug) logger.debug("addListenerWithSubject","listenerID="
-                + listenerIDs[0]);
-        return listenerIDs[0];
-    }
-
-    // added for re-connection
-    private Integer[] addListenersWithSubjects(ObjectName[]       names,
-                             MarshalledObject<NotificationFilter>[] filters,
-                             Subject[]          delegationSubjects,
-                             boolean            reconnect)
-        throws InstanceNotFoundException, IOException {
-
-        final boolean debug = logger.debugOn();
-        if (debug)
-            logger.debug("addListenersWithSubjects",
-                    "(ObjectName[],MarshalledObject[],Subject[])");
-
-        final ClassLoader old = pushDefaultClassLoader();
-        Integer[] listenerIDs = null;
-
-        try {
-            listenerIDs = connection.addNotificationListeners(names,
-                    filters,
-                    delegationSubjects);
-        } catch (NoSuchObjectException noe) {
-            // maybe reconnect
-            if (reconnect) {
-                communicatorAdmin.gotIOException(noe);
-
-                listenerIDs = connection.addNotificationListeners(names,
-                        filters,
-                        delegationSubjects);
-            } else {
-                throw noe;
-            }
-        } catch (IOException ioe) {
-            // send a failed notif if necessary
-            communicatorAdmin.gotIOException(ioe);
-        } finally {
-            popDefaultClassLoader(old);
-        }
-
-        if (debug) logger.debug("addListenersWithSubjects","registered "
-                + ((listenerIDs==null)?0:listenerIDs.length)
-                + " listener(s)");
-        return listenerIDs;
-    }
-
-    //--------------------------------------------------------------------
-    // Implementation of MBeanServerConnection
-    //--------------------------------------------------------------------
-    private class RemoteMBeanServerConnection implements MBeanServerConnection {
-        private Subject delegationSubject;
-
-        public RemoteMBeanServerConnection() {
-            this(null);
-        }
-
-        public RemoteMBeanServerConnection(Subject delegationSubject) {
-            this.delegationSubject = delegationSubject;
-        }
-
-        public ObjectInstance createMBean(String className,
-                ObjectName name)
-                throws ReflectionException,
-                InstanceAlreadyExistsException,
-                MBeanRegistrationException,
-                MBeanException,
-                NotCompliantMBeanException,
-                IOException {
-            if (logger.debugOn())
-                logger.debug("createMBean(String,ObjectName)",
-                        "className=" + className + ", name=" +
-                        name);
-
-            final ClassLoader old = pushDefaultClassLoader();
-            try {
-                return connection.createMBean(className,
-                        name,
-                        delegationSubject);
-            } catch (IOException ioe) {
-                communicatorAdmin.gotIOException(ioe);
-
-                return connection.createMBean(className,
-                        name,
-                        delegationSubject);
-            } finally {
-                popDefaultClassLoader(old);
-            }
-        }
-
-        public ObjectInstance createMBean(String className,
-                ObjectName name,
-                ObjectName loaderName)
-                throws ReflectionException,
-                InstanceAlreadyExistsException,
-                MBeanRegistrationException,
-                MBeanException,
-                NotCompliantMBeanException,
-                InstanceNotFoundException,
-                IOException {
-
-            if (logger.debugOn())
-                logger.debug("createMBean(String,ObjectName,ObjectName)",
-                        "className=" + className + ", name="
-                        + name + ", loaderName="
-                        + loaderName + ")");
-
-            final ClassLoader old = pushDefaultClassLoader();
-            try {
-                return connection.createMBean(className,
-                        name,
-                        loaderName,
-                        delegationSubject);
-
-            } catch (IOException ioe) {
-                communicatorAdmin.gotIOException(ioe);
-
-                return connection.createMBean(className,
-                        name,
-                        loaderName,
-                        delegationSubject);
-
-            } finally {
-                popDefaultClassLoader(old);
-            }
-        }
-
-        public ObjectInstance createMBean(String className,
-                ObjectName name,
-                Object params[],
-                String signature[])
-                throws ReflectionException,
-                InstanceAlreadyExistsException,
-                MBeanRegistrationException,
-                MBeanException,
-                NotCompliantMBeanException,
-                IOException {
-            if (logger.debugOn())
-                logger.debug("createMBean(String,ObjectName,Object[],String[])",
-                        "className=" + className + ", name="
-                        + name + ", signature=" + strings(signature));
-
-            final MarshalledObject<Object[]> sParams =
-                    new MarshalledObject<Object[]>(params);
-            final ClassLoader old = pushDefaultClassLoader();
-            try {
-                return connection.createMBean(className,
-                        name,
-                        sParams,
-                        signature,
-                        delegationSubject);
-            } catch (IOException ioe) {
-                communicatorAdmin.gotIOException(ioe);
-
-                return connection.createMBean(className,
-                        name,
-                        sParams,
-                        signature,
-                        delegationSubject);
-            } finally {
-                popDefaultClassLoader(old);
-            }
-        }
-
-        public ObjectInstance createMBean(String className,
-                ObjectName name,
-                ObjectName loaderName,
-                Object params[],
-                String signature[])
-                throws ReflectionException,
-                InstanceAlreadyExistsException,
-                MBeanRegistrationException,
-                MBeanException,
-                NotCompliantMBeanException,
-                InstanceNotFoundException,
-                IOException {
-            if (logger.debugOn()) logger.debug(
-                    "createMBean(String,ObjectName,ObjectName,Object[],String[])",
-                    "className=" + className + ", name=" + name + ", loaderName="
-                    + loaderName + ", signature=" + strings(signature));
-
-            final MarshalledObject<Object[]> sParams =
-                    new MarshalledObject<Object[]>(params);
-            final ClassLoader old = pushDefaultClassLoader();
-            try {
-                return connection.createMBean(className,
-                        name,
-                        loaderName,
-                        sParams,
-                        signature,
-                        delegationSubject);
-            } catch (IOException ioe) {
-                communicatorAdmin.gotIOException(ioe);
-
-                return connection.createMBean(className,
-                        name,
-                        loaderName,
-                        sParams,
-                        signature,
-                        delegationSubject);
-            } finally {
-                popDefaultClassLoader(old);
-            }
-        }
-
-        public void unregisterMBean(ObjectName name)
-        throws InstanceNotFoundException,
-                MBeanRegistrationException,
-                IOException {
-            if (logger.debugOn())
-                logger.debug("unregisterMBean", "name=" + name);
-
-            final ClassLoader old = pushDefaultClassLoader();
-            try {
-                connection.unregisterMBean(name, delegationSubject);
-            } catch (IOException ioe) {
-                communicatorAdmin.gotIOException(ioe);
-
-                connection.unregisterMBean(name, delegationSubject);
-            } finally {
-                popDefaultClassLoader(old);
-            }
-        }
-
-        public ObjectInstance getObjectInstance(ObjectName name)
-        throws InstanceNotFoundException,
-                IOException {
-            if (logger.debugOn())
-                logger.debug("getObjectInstance", "name=" + name);
-
-            final ClassLoader old = pushDefaultClassLoader();
-            try {
-                return connection.getObjectInstance(name, delegationSubject);
-            } catch (IOException ioe) {
-                communicatorAdmin.gotIOException(ioe);
-
-                return connection.getObjectInstance(name, delegationSubject);
-            } finally {
-                popDefaultClassLoader(old);
-            }
-        }
-
-        public Set<ObjectInstance> queryMBeans(ObjectName name,
-                QueryExp query)
-                throws IOException {
-            if (logger.debugOn()) logger.debug("queryMBeans",
-                    "name=" + name + ", query=" + query);
-
-            final MarshalledObject<QueryExp> sQuery =
-                    new MarshalledObject<QueryExp>(query);
-            final ClassLoader old = pushDefaultClassLoader();
-            try {
-                return connection.queryMBeans(name, sQuery, delegationSubject);
-            } catch (IOException ioe) {
-                communicatorAdmin.gotIOException(ioe);
-
-                return connection.queryMBeans(name, sQuery, delegationSubject);
-            } finally {
-                popDefaultClassLoader(old);
-            }
-        }
-
-        public Set<ObjectName> queryNames(ObjectName name,
-                QueryExp query)
-                throws IOException {
-            if (logger.debugOn()) logger.debug("queryNames",
-                    "name=" + name + ", query=" + query);
-
-            final MarshalledObject<QueryExp> sQuery =
-                    new MarshalledObject<QueryExp>(query);
-            final ClassLoader old = pushDefaultClassLoader();
-            try {
-                return connection.queryNames(name, sQuery, delegationSubject);
-            } catch (IOException ioe) {
-                communicatorAdmin.gotIOException(ioe);
-
-                return connection.queryNames(name, sQuery, delegationSubject);
-            } finally {
-                popDefaultClassLoader(old);
-            }
-        }
-
-        public boolean isRegistered(ObjectName name)
-        throws IOException {
-            if (logger.debugOn())
-                logger.debug("isRegistered", "name=" + name);
-
-            final ClassLoader old = pushDefaultClassLoader();
-            try {
-                return connection.isRegistered(name, delegationSubject);
-            } catch (IOException ioe) {
-                communicatorAdmin.gotIOException(ioe);
-
-                return connection.isRegistered(name, delegationSubject);
-            } finally {
-                popDefaultClassLoader(old);
-            }
-        }
-
-        public Integer getMBeanCount()
-        throws IOException {
-            if (logger.debugOn()) logger.debug("getMBeanCount", "");
-
-            final ClassLoader old = pushDefaultClassLoader();
-            try {
-                return connection.getMBeanCount(delegationSubject);
-            } catch (IOException ioe) {
-                communicatorAdmin.gotIOException(ioe);
-
-                return connection.getMBeanCount(delegationSubject);
-            } finally {
-                popDefaultClassLoader(old);
-            }
-        }
-
-        public Object getAttribute(ObjectName name,
-                String attribute)
-                throws MBeanException,
-                AttributeNotFoundException,
-                InstanceNotFoundException,
-                ReflectionException,
-                IOException {
-            if (logger.debugOn()) logger.debug("getAttribute",
-                    "name=" + name + ", attribute="
-                    + attribute);
-
-            final ClassLoader old = pushDefaultClassLoader();
-            try {
-                return connection.getAttribute(name,
-                        attribute,
-                        delegationSubject);
-            } catch (IOException ioe) {
-                communicatorAdmin.gotIOException(ioe);
-
-                return connection.getAttribute(name,
-                        attribute,
-                        delegationSubject);
-            } finally {
-                popDefaultClassLoader(old);
-            }
-        }
-
-        public AttributeList getAttributes(ObjectName name,
-                String[] attributes)
-                throws InstanceNotFoundException,
-                ReflectionException,
-                IOException {
-            if (logger.debugOn()) logger.debug("getAttributes",
-                    "name=" + name + ", attributes="
-                    + strings(attributes));
-
-            final ClassLoader old = pushDefaultClassLoader();
-            try {
-                return connection.getAttributes(name,
-                        attributes,
-                        delegationSubject);
-
-            } catch (IOException ioe) {
-                communicatorAdmin.gotIOException(ioe);
-
-                return connection.getAttributes(name,
-                        attributes,
-                        delegationSubject);
-            } finally {
-                popDefaultClassLoader(old);
-            }
-        }
-
-
-        public void setAttribute(ObjectName name,
-                Attribute attribute)
-                throws InstanceNotFoundException,
-                AttributeNotFoundException,
-                InvalidAttributeValueException,
-                MBeanException,
-                ReflectionException,
-                IOException {
-
-            if (logger.debugOn()) logger.debug("setAttribute",
-                    "name=" + name + ", attribute name="
-                    + attribute.getName());
-
-            final MarshalledObject<Attribute> sAttribute =
-                    new MarshalledObject<Attribute>(attribute);
-            final ClassLoader old = pushDefaultClassLoader();
-            try {
-                connection.setAttribute(name, sAttribute, delegationSubject);
-            } catch (IOException ioe) {
-                communicatorAdmin.gotIOException(ioe);
-
-                connection.setAttribute(name, sAttribute, delegationSubject);
-            } finally {
-                popDefaultClassLoader(old);
-            }
-        }
-
-        public AttributeList setAttributes(ObjectName name,
-                AttributeList attributes)
-                throws InstanceNotFoundException,
-                ReflectionException,
-                IOException {
-
-            if (logger.debugOn()) {
-                logger.debug("setAttributes",
-                    "name=" + name + ", attribute names="
-                    + getAttributesNames(attributes));
-            }
-
-            final MarshalledObject<AttributeList> sAttributes =
-                    new MarshalledObject<AttributeList>(attributes);
-            final ClassLoader old = pushDefaultClassLoader();
-            try {
-                return connection.setAttributes(name,
-                        sAttributes,
-                        delegationSubject);
-            } catch (IOException ioe) {
-                communicatorAdmin.gotIOException(ioe);
-
-                return connection.setAttributes(name,
-                        sAttributes,
-                        delegationSubject);
-            } finally {
-                popDefaultClassLoader(old);
-            }
-        }
-
-
-        public Object invoke(ObjectName name,
-                String operationName,
-                Object params[],
-                String signature[])
-                throws InstanceNotFoundException,
-                MBeanException,
-                ReflectionException,
-                IOException {
-
-            if (logger.debugOn()) logger.debug("invoke",
-                    "name=" + name
-                    + ", operationName=" + operationName
-                    + ", signature=" + strings(signature));
-
-            final MarshalledObject<Object[]> sParams =
-                    new MarshalledObject<Object[]>(params);
-            final ClassLoader old = pushDefaultClassLoader();
-            try {
-                return connection.invoke(name,
-                        operationName,
-                        sParams,
-                        signature,
-                        delegationSubject);
-            } catch (IOException ioe) {
-                communicatorAdmin.gotIOException(ioe);
-
-                return connection.invoke(name,
-                        operationName,
-                        sParams,
-                        signature,
-                        delegationSubject);
-            } finally {
-                popDefaultClassLoader(old);
-            }
-        }
-
-
-        public String getDefaultDomain()
-        throws IOException {
-            if (logger.debugOn()) logger.debug("getDefaultDomain", "");
-
-            final ClassLoader old = pushDefaultClassLoader();
-            try {
-                return connection.getDefaultDomain(delegationSubject);
-            } catch (IOException ioe) {
-                communicatorAdmin.gotIOException(ioe);
-
-                return connection.getDefaultDomain(delegationSubject);
-            } finally {
-                popDefaultClassLoader(old);
-            }
-        }
-
-        public String[] getDomains() throws IOException {
-            if (logger.debugOn()) logger.debug("getDomains", "");
-
-            final ClassLoader old = pushDefaultClassLoader();
-            try {
-                return connection.getDomains(delegationSubject);
-            } catch (IOException ioe) {
-                communicatorAdmin.gotIOException(ioe);
-
-                return connection.getDomains(delegationSubject);
-            } finally {
-                popDefaultClassLoader(old);
-            }
-        }
-
-        public MBeanInfo getMBeanInfo(ObjectName name)
-        throws InstanceNotFoundException,
-                IntrospectionException,
-                ReflectionException,
-                IOException {
-
-            if (logger.debugOn()) logger.debug("getMBeanInfo", "name=" + name);
-            final ClassLoader old = pushDefaultClassLoader();
-            try {
-                return connection.getMBeanInfo(name, delegationSubject);
-            } catch (IOException ioe) {
-                communicatorAdmin.gotIOException(ioe);
-
-                return connection.getMBeanInfo(name, delegationSubject);
-            } finally {
-                popDefaultClassLoader(old);
-            }
-        }
-
-
-        public boolean isInstanceOf(ObjectName name,
-                String className)
-                throws InstanceNotFoundException,
-                IOException {
-            if (logger.debugOn())
-                logger.debug("isInstanceOf", "name=" + name +
-                        ", className=" + className);
-
-            final ClassLoader old = pushDefaultClassLoader();
-            try {
-                return connection.isInstanceOf(name,
-                        className,
-                        delegationSubject);
-            } catch (IOException ioe) {
-                communicatorAdmin.gotIOException(ioe);
-
-                return connection.isInstanceOf(name,
-                        className,
-                        delegationSubject);
-            } finally {
-                popDefaultClassLoader(old);
-            }
-        }
-
-        public void addNotificationListener(ObjectName name,
-                ObjectName listener,
-                NotificationFilter filter,
-                Object handback)
-                throws InstanceNotFoundException,
-                IOException {
-
-            if (logger.debugOn())
-                logger.debug("addNotificationListener" +
-                        "(ObjectName,ObjectName,NotificationFilter,Object)",
-                        "name=" + name + ", listener=" + listener
-                        + ", filter=" + filter + ", handback=" + handback);
-
-            final MarshalledObject<NotificationFilter> sFilter =
-                    new MarshalledObject<NotificationFilter>(filter);
-            final MarshalledObject<Object> sHandback =
-                    new MarshalledObject<Object>(handback);
-            final ClassLoader old = pushDefaultClassLoader();
-            try {
-                connection.addNotificationListener(name,
-                        listener,
-                        sFilter,
-                        sHandback,
-                        delegationSubject);
-            } catch (IOException ioe) {
-                communicatorAdmin.gotIOException(ioe);
-
-                connection.addNotificationListener(name,
-                        listener,
-                        sFilter,
-                        sHandback,
-                        delegationSubject);
-            } finally {
-                popDefaultClassLoader(old);
-            }
-        }
-
-        public void removeNotificationListener(ObjectName name,
-                ObjectName listener)
-                throws InstanceNotFoundException,
-                ListenerNotFoundException,
-                IOException {
-
-            if (logger.debugOn()) logger.debug("removeNotificationListener" +
-                    "(ObjectName,ObjectName)",
-                    "name=" + name
-                    + ", listener=" + listener);
-
-            final ClassLoader old = pushDefaultClassLoader();
-            try {
-                connection.removeNotificationListener(name,
-                        listener,
-                        delegationSubject);
-            } catch (IOException ioe) {
-                communicatorAdmin.gotIOException(ioe);
-
-                connection.removeNotificationListener(name,
-                        listener,
-                        delegationSubject);
-            } finally {
-                popDefaultClassLoader(old);
-            }
-        }
-
-        public void removeNotificationListener(ObjectName name,
-                ObjectName listener,
-                NotificationFilter filter,
-                Object handback)
-                throws InstanceNotFoundException,
-                ListenerNotFoundException,
-                IOException {
-            if (logger.debugOn())
-                logger.debug("removeNotificationListener" +
-                        "(ObjectName,ObjectName,NotificationFilter,Object)",
-                        "name=" + name
-                        + ", listener=" + listener
-                        + ", filter=" + filter
-                        + ", handback=" + handback);
-
-            final MarshalledObject<NotificationFilter> sFilter =
-                    new MarshalledObject<NotificationFilter>(filter);
-            final MarshalledObject<Object> sHandback =
-                    new MarshalledObject<Object>(handback);
-            final ClassLoader old = pushDefaultClassLoader();
-            try {
-                connection.removeNotificationListener(name,
-                        listener,
-                        sFilter,
-                        sHandback,
-                        delegationSubject);
-            } catch (IOException ioe) {
-                communicatorAdmin.gotIOException(ioe);
-
-                connection.removeNotificationListener(name,
-                        listener,
-                        sFilter,
-                        sHandback,
-                        delegationSubject);
-            } finally {
-                popDefaultClassLoader(old);
-            }
-        }
-
-        // Specific Notification Handle ----------------------------------
-
-        public void addNotificationListener(ObjectName name,
-                NotificationListener listener,
-                NotificationFilter filter,
-                Object handback)
-                throws InstanceNotFoundException,
-                IOException {
-
-            final boolean debug = logger.debugOn();
-
-            if (debug)
-                logger.debug("addNotificationListener" +
-                        "(ObjectName,NotificationListener,"+
-                        "NotificationFilter,Object)",
-                        "name=" + name
-                        + ", listener=" + listener
-                        + ", filter=" + filter
-                        + ", handback=" + handback);
-
-            final Integer listenerID =
-                    addListenerWithSubject(name,
-                    new MarshalledObject<NotificationFilter>(filter),
-                    delegationSubject,true);
-            rmiNotifClient.addNotificationListener(listenerID, name, listener,
-                    filter, handback,
-                    delegationSubject);
-        }
-
-        public void removeNotificationListener(ObjectName name,
-                NotificationListener listener)
-                throws InstanceNotFoundException,
-                ListenerNotFoundException,
-                IOException {
-
-            final boolean debug = logger.debugOn();
-
-            if (debug) logger.debug("removeNotificationListener"+
-                    "(ObjectName,NotificationListener)",
-                    "name=" + name
-                    + ", listener=" + listener);
-
-            final Integer[] ret =
-                    rmiNotifClient.removeNotificationListener(name, listener);
-
-            if (debug) logger.debug("removeNotificationListener",
-                    "listenerIDs=" + objects(ret));
-
-            final ClassLoader old = pushDefaultClassLoader();
-
-            try {
-                connection.removeNotificationListeners(name,
-                        ret,
-                        delegationSubject);
-            } catch (IOException ioe) {
-                communicatorAdmin.gotIOException(ioe);
-
-                connection.removeNotificationListeners(name,
-                        ret,
-                        delegationSubject);
-            } finally {
-                popDefaultClassLoader(old);
-            }
-
-        }
-
-        public void removeNotificationListener(ObjectName name,
-                NotificationListener listener,
-                NotificationFilter filter,
-                Object handback)
-                throws InstanceNotFoundException,
-                ListenerNotFoundException,
-                IOException {
-            final boolean debug = logger.debugOn();
-
-            if (debug)
-                logger.debug("removeNotificationListener"+
-                        "(ObjectName,NotificationListener,"+
-                        "NotificationFilter,Object)",
-                        "name=" + name
-                        + ", listener=" + listener
-                        + ", filter=" + filter
-                        + ", handback=" + handback);
-
-            final Integer ret =
-                    rmiNotifClient.removeNotificationListener(name, listener,
-                    filter, handback);
-
-            if (debug) logger.debug("removeNotificationListener",
-                    "listenerID=" + ret);
-
-            final ClassLoader old = pushDefaultClassLoader();
-            try {
-                connection.removeNotificationListeners(name,
-                        new Integer[] {ret},
-                        delegationSubject);
-            } catch (IOException ioe) {
-                communicatorAdmin.gotIOException(ioe);
-
-                connection.removeNotificationListeners(name,
-                        new Integer[] {ret},
-                        delegationSubject);
-            } finally {
-                popDefaultClassLoader(old);
-            }
-
-        }
-    }
-
-    //--------------------------------------------------------------------
-    private class RMINotifClient extends ClientNotifForwarder {
-        public RMINotifClient(ClassLoader cl, Map<String, ?> env) {
-            super(cl, env);
-        }
-
-        protected NotificationResult fetchNotifs(long clientSequenceNumber,
-                int maxNotifications,
-                long timeout)
-                throws IOException, ClassNotFoundException {
-
-            boolean retried = false;
-            while (true) { // used for a successful re-connection
-                           // or a transient network problem
-                try {
-                    return connection.fetchNotifications(clientSequenceNumber,
-                            maxNotifications,
-                            timeout); // return normally
-                } catch (IOException ioe) {
-                    // Examine the chain of exceptions to determine whether this
-                    // is a deserialization issue. If so - we propagate the
-                    // appropriate exception to the caller, who will then
-                    // proceed with fetching notifications one by one
-                    rethrowDeserializationException(ioe);
-
-                    try {
-                        communicatorAdmin.gotIOException(ioe);
-                        // reconnection OK, back to "while" to do again
-                    } catch (IOException ee) {
-                        boolean toClose = false;
-
-                        synchronized (this) {
-                            if (terminated) {
-                                // the connection is closed.
-                                throw ioe;
-                            } else if (retried) {
-                                toClose = true;
-                            }
-                        }
-
-                        if (toClose) {
-                            // JDK-8049303
-                            // We received an IOException - but the communicatorAdmin
-                            // did not close the connection - possibly because
-                            // the original exception was raised by a transient network
-                            // problem?
-                            // We already know that this exception is not due to a deserialization
-                            // issue as we already took care of that before involving the
-                            // communicatorAdmin. Moreover - we already made one retry attempt
-                            // at fetching the same batch of notifications - and the
-                            // problem persisted.
-                            // Since trying again doesn't seem to solve the issue, we will now
-                            // close the connection. Doing otherwise might cause the
-                            // NotifFetcher thread to die silently.
-                            final Notification failedNotif =
-                                    new JMXConnectionNotification(
-                                    JMXConnectionNotification.FAILED,
-                                    this,
-                                    connectionId,
-                                    clientNotifSeqNo++,
-                                    "Failed to communicate with the server: " + ioe.toString(),
-                                    ioe);
-
-                            sendNotification(failedNotif);
-
-                            try {
-                                close(true);
-                            } catch (Exception e) {
-                                // OK.
-                                // We are closing
-                            }
-                            throw ioe; // the connection is closed here.
-                        } else {
-                            // JDK-8049303 possible transient network problem,
-                            // let's try one more time
-                            retried = true;
-                        }
-                    }
-                }
-            }
-        }
-
-        private void rethrowDeserializationException(IOException ioe)
-                throws ClassNotFoundException, IOException {
-            // specially treating for an UnmarshalException
-            if (ioe instanceof UnmarshalException) {
-                throw ioe; // the fix of 6937053 made ClientNotifForwarder.fetchNotifs
-                           // fetch one by one with UnmarshalException
-            }
-
-            // Not serialization problem, return.
-        }
-
-        protected Integer addListenerForMBeanRemovedNotif()
-        throws IOException, InstanceNotFoundException {
-            NotificationFilterSupport clientFilter =
-                    new NotificationFilterSupport();
-            clientFilter.enableType(
-                    MBeanServerNotification.UNREGISTRATION_NOTIFICATION);
-            MarshalledObject<NotificationFilter> sFilter =
-                new MarshalledObject<NotificationFilter>(clientFilter);
-
-            Integer[] listenerIDs;
-            final ObjectName[] names =
-                new ObjectName[] {MBeanServerDelegate.DELEGATE_NAME};
-            final MarshalledObject<NotificationFilter>[] filters =
-                Util.cast(new MarshalledObject<?>[] {sFilter});
-            final Subject[] subjects = new Subject[] {null};
-            try {
-                listenerIDs =
-                        connection.addNotificationListeners(names,
-                        filters,
-                        subjects);
-
-            } catch (IOException ioe) {
-                communicatorAdmin.gotIOException(ioe);
-
-                listenerIDs =
-                        connection.addNotificationListeners(names,
-                        filters,
-                        subjects);
-            }
-            return listenerIDs[0];
-        }
-
-        protected void removeListenerForMBeanRemovedNotif(Integer id)
-        throws IOException, InstanceNotFoundException,
-                ListenerNotFoundException {
-            try {
-                connection.removeNotificationListeners(
-                        MBeanServerDelegate.DELEGATE_NAME,
-                        new Integer[] {id},
-                        null);
-            } catch (IOException ioe) {
-                communicatorAdmin.gotIOException(ioe);
-
-                connection.removeNotificationListeners(
-                        MBeanServerDelegate.DELEGATE_NAME,
-                        new Integer[] {id},
-                        null);
-            }
-
-        }
-
-        protected void lostNotifs(String message, long number) {
-            final String notifType = JMXConnectionNotification.NOTIFS_LOST;
-
-            final JMXConnectionNotification n =
-                new JMXConnectionNotification(notifType,
-                                              RMIConnector.this,
-                                              connectionId,
-                                              clientNotifCounter++,
-                                              message,
-                                              Long.valueOf(number));
-            sendNotification(n);
-        }
-    }
-
-    private class RMIClientCommunicatorAdmin extends ClientCommunicatorAdmin {
-        public RMIClientCommunicatorAdmin(long period) {
-            super(period);
-        }
-
-        @Override
-        public void gotIOException(IOException ioe) throws IOException {
-            if (ioe instanceof NoSuchObjectException) {
-                // need to restart
-                super.gotIOException(ioe);
-
-                return;
-            }
-
-            // check if the connection is broken
-            try {
-                connection.getDefaultDomain(null);
-            } catch (IOException ioexc) {
-                boolean toClose = false;
-
-                synchronized(this) {
-                    if (!terminated) {
-                        terminated = true;
-
-                        toClose = true;
-                    }
-                }
-
-                if (toClose) {
-                    // we should close the connection,
-                    // but send a failed notif at first
-                    final Notification failedNotif =
-                            new JMXConnectionNotification(
-                            JMXConnectionNotification.FAILED,
-                            this,
-                            connectionId,
-                            clientNotifSeqNo++,
-                            "Failed to communicate with the server: "+ioe.toString(),
-                            ioe);
-
-                    sendNotification(failedNotif);
-
-                    try {
-                        close(true);
-                    } catch (Exception e) {
-                        // OK.
-                        // We are closing
-                    }
-                }
-            }
-
-            // forward the exception
-            if (ioe instanceof ServerException) {
-                /* Need to unwrap the exception.
-                   Some user-thrown exception at server side will be wrapped by
-                   rmi into a ServerException.
-                   For example, a RMIConnnectorServer will wrap a
-                   ClassNotFoundException into a UnmarshalException, and rmi
-                   will throw a ServerException at client side which wraps this
-                   UnmarshalException.
-                   No failed notif here.
-                 */
-                Throwable tt = ((ServerException)ioe).detail;
-
-                if (tt instanceof IOException) {
-                    throw (IOException)tt;
-                } else if (tt instanceof RuntimeException) {
-                    throw (RuntimeException)tt;
-                }
-            }
-
-            throw ioe;
-        }
-
-        public void reconnectNotificationListeners(ClientListenerInfo[] old) throws IOException {
-            final int len  = old.length;
-            int i;
-
-            ClientListenerInfo[] clis = new ClientListenerInfo[len];
-
-            final Subject[] subjects = new Subject[len];
-            final ObjectName[] names = new ObjectName[len];
-            final NotificationListener[] listeners = new NotificationListener[len];
-            final NotificationFilter[] filters = new NotificationFilter[len];
-            final MarshalledObject<NotificationFilter>[] mFilters =
-                    Util.cast(new MarshalledObject<?>[len]);
-            final Object[] handbacks = new Object[len];
-
-            for (i=0;i<len;i++) {
-                subjects[i]  = old[i].getDelegationSubject();
-                names[i]     = old[i].getObjectName();
-                listeners[i] = old[i].getListener();
-                filters[i]   = old[i].getNotificationFilter();
-                mFilters[i]  = new MarshalledObject<NotificationFilter>(filters[i]);
-                handbacks[i] = old[i].getHandback();
-            }
-
-            try {
-                Integer[] ids = addListenersWithSubjects(names,mFilters,subjects,false);
-
-                for (i=0;i<len;i++) {
-                    clis[i] = new ClientListenerInfo(ids[i],
-                            names[i],
-                            listeners[i],
-                            filters[i],
-                            handbacks[i],
-                            subjects[i]);
-                }
-
-                rmiNotifClient.postReconnection(clis);
-
-                return;
-            } catch (InstanceNotFoundException infe) {
-                // OK, we will do one by one
-            }
-
-            int j = 0;
-            for (i=0;i<len;i++) {
-                try {
-                    Integer id = addListenerWithSubject(names[i],
-                            new MarshalledObject<NotificationFilter>(filters[i]),
-                            subjects[i],
-                            false);
-
-                    clis[j++] = new ClientListenerInfo(id,
-                            names[i],
-                            listeners[i],
-                            filters[i],
-                            handbacks[i],
-                            subjects[i]);
-                } catch (InstanceNotFoundException infe) {
-                    logger.warning("reconnectNotificationListeners",
-                            "Can't reconnect listener for " +
-                            names[i]);
-                }
-            }
-
-            if (j != len) {
-                ClientListenerInfo[] tmp = clis;
-                clis = new ClientListenerInfo[j];
-                System.arraycopy(tmp, 0, clis, 0, j);
-            }
-
-            rmiNotifClient.postReconnection(clis);
-        }
-
-        protected void checkConnection() throws IOException {
-            if (logger.debugOn())
-                logger.debug("RMIClientCommunicatorAdmin-checkConnection",
-                        "Calling the method getDefaultDomain.");
-
-            connection.getDefaultDomain(null);
-        }
-
-        protected void doStart() throws IOException {
-            // Get RMIServer stub from directory or URL encoding if needed.
-            RMIServer stub;
-            try {
-                stub = (rmiServer!=null)?rmiServer:
-                    findRMIServer(jmxServiceURL, env);
-            } catch (NamingException ne) {
-                throw new IOException("Failed to get a RMI stub: "+ne);
-            }
-
-            // Calling newClient on the RMIServer stub.
-            Object credentials = env.get(CREDENTIALS);
-            connection = stub.newClient(credentials);
-
-            // notif issues
-            final ClientListenerInfo[] old = rmiNotifClient.preReconnection();
-
-            reconnectNotificationListeners(old);
-
-            connectionId = getConnectionId();
-
-            Notification reconnectedNotif =
-                    new JMXConnectionNotification(JMXConnectionNotification.OPENED,
-                    this,
-                    connectionId,
-                    clientNotifSeqNo++,
-                    "Reconnected to server",
-                    null);
-            sendNotification(reconnectedNotif);
-
-        }
-
-        protected void doStop() {
-            try {
-                close();
-            } catch (IOException ioe) {
-                logger.warning("RMIClientCommunicatorAdmin-doStop",
-                        "Failed to call the method close():" + ioe);
-                logger.debug("RMIClientCommunicatorAdmin-doStop",ioe);
-            }
-        }
-    }
-
-    //--------------------------------------------------------------------
-    // Private stuff - Serialization
-    //--------------------------------------------------------------------
-    /**
-     * Read RMIConnector fields from an {@link java.io.ObjectInputStream
-     * ObjectInputStream}.
-     * Calls {@code s.defaultReadObject()} and then initializes
-     * all transient variables that need initializing.
-     * @param s The ObjectInputStream to read from.
-     * @exception InvalidObjectException if none of <var>rmiServer</var> stub
-     *    or <var>jmxServiceURL</var> are set.
-     * @see #RMIConnector(JMXServiceURL,Map)
-     * @see #RMIConnector(RMIServer,Map)
-     **/
-    private void readObject(java.io.ObjectInputStream s)
-    throws IOException, ClassNotFoundException  {
-        s.defaultReadObject();
-
-        if (rmiServer == null && jmxServiceURL == null) throw new
-                InvalidObjectException("rmiServer and jmxServiceURL both null");
-
-        initTransients();
-    }
-
-    /**
-     * Writes the RMIConnector fields to an {@link java.io.ObjectOutputStream
-     * ObjectOutputStream}.
-     * <p>Connects the underlying RMIServer stub to an ORB, if needed,
-     * before serializing it. This is done using the environment
-     * map that was provided to the constructor, if any, and as documented
-     * in {@link javax.management.remote.rmi}.</p>
-     * <p>This method then calls {@code s.defaultWriteObject()}.
-     * Usually, <var>rmiServer</var> is null if this object
-     * was constructed with a JMXServiceURL, and <var>jmxServiceURL</var>
-     * is null if this object is constructed with a RMIServer stub.
-     * <p>Note that the environment Map is not serialized, since the objects
-     * it contains are assumed to be contextual and relevant only
-     * with respect to the local environment (class loader, ORB, etc...).</p>
-     * <p>After an RMIConnector is deserialized, it is assumed that the
-     * user will call {@link #connect(Map)}, providing a new Map that
-     * can contain values which are contextually relevant to the new
-     * local environment.</p>
-     * <p>Since connection to the ORB is needed prior to serializing, and
-     * since the ORB to connect to is one of those contextual parameters,
-     * it is not recommended to re-serialize a just de-serialized object -
-     * as the de-serialized object has no map. Thus, when an RMIConnector
-     * object is needed for serialization or transmission to a remote
-     * application, it is recommended to obtain a new RMIConnector stub
-     * by calling {@link RMIConnectorServer#toJMXConnector(Map)}.</p>
-     * @param s The ObjectOutputStream to write to.
-     * @exception InvalidObjectException if none of <var>rmiServer</var> stub
-     *    or <var>jmxServiceURL</var> are set.
-     * @see #RMIConnector(JMXServiceURL,Map)
-     * @see #RMIConnector(RMIServer,Map)
-     **/
-    private void writeObject(java.io.ObjectOutputStream s)
-    throws IOException {
-        if (rmiServer == null && jmxServiceURL == null) throw new
-                InvalidObjectException("rmiServer and jmxServiceURL both null.");
-        s.defaultWriteObject();
-    }
-
-    // Initialization of transient variables.
-    private void initTransients() {
-        rmbscMap = new WeakHashMap<Subject, WeakReference<MBeanServerConnection>>();
-        connected = false;
-        terminated = false;
-
-        connectionBroadcaster = new NotificationBroadcasterSupport();
-    }
-
-    //--------------------------------------------------------------------
-    // Private stuff - Check if stub can be trusted.
-    //--------------------------------------------------------------------
-
-    private static void checkStub(Remote stub,
-            Class<?> stubClass) {
-
-        // Check remote stub is from the expected class.
-        //
-        if (stub.getClass() != stubClass) {
-            if (!Proxy.isProxyClass(stub.getClass())) {
-                throw new SecurityException(
-                        "Expecting a " + stubClass.getName() + " stub!");
-            } else {
-                InvocationHandler handler = Proxy.getInvocationHandler(stub);
-                if (handler.getClass() != RemoteObjectInvocationHandler.class)
-                    throw new SecurityException(
-                            "Expecting a dynamic proxy instance with a " +
-                            RemoteObjectInvocationHandler.class.getName() +
-                            " invocation handler!");
-                else
-                    stub = (Remote) handler;
-            }
-        }
-
-        // Check RemoteRef in stub is from the expected class
-        // "sun.rmi.server.UnicastRef2".
-        //
-        RemoteRef ref = ((RemoteObject)stub).getRef();
-        if (ref.getClass() != UnicastRef2.class)
-            throw new SecurityException(
-                    "Expecting a " + UnicastRef2.class.getName() +
-                    " remote reference in stub!");
-
-        // Check RMIClientSocketFactory in stub is from the expected class
-        // "javax.rmi.ssl.SslRMIClientSocketFactory".
-        //
-        LiveRef liveRef = ((UnicastRef2)ref).getLiveRef();
-        RMIClientSocketFactory csf = liveRef.getClientSocketFactory();
-        if (csf == null || csf.getClass() != SslRMIClientSocketFactory.class)
-            throw new SecurityException(
-                    "Expecting a " + SslRMIClientSocketFactory.class.getName() +
-                    " RMI client socket factory in stub!");
-    }
-
-    //--------------------------------------------------------------------
-    // Private stuff - RMIServer creation
-    //--------------------------------------------------------------------
-
-    private RMIServer findRMIServer(JMXServiceURL directoryURL,
-            Map<String, Object> environment)
-            throws NamingException, IOException {
-
-        String path = directoryURL.getURLPath();
-        int end = path.indexOf(';');
-        if (end < 0) end = path.length();
-        if (path.startsWith("/jndi/"))
-            return findRMIServerJNDI(path.substring(6,end), environment);
-        else if (path.startsWith("/stub/"))
-            return findRMIServerJRMP(path.substring(6,end), environment);
-        else {
-            final String msg = "URL path must begin with /jndi/ or /stub/ " +
-                    "or /ior/: " + path;
-            throw new MalformedURLException(msg);
-        }
-    }
-
-    /**
-     * Lookup the RMIServer stub in a directory.
-     * @param jndiURL A JNDI URL indicating the location of the Stub
-     *                (see {@link javax.management.remote.rmi}), e.g.:
-     *   <ul><li>{@code rmi://registry-host:port/rmi-stub-name}</li>
-     *       <li>or {@code ldap://ldap-host:port/java-container-dn}</li>
-     *   </ul>
-     * @param env the environment Map passed to the connector.
-     * @return The retrieved RMIServer stub.
-     * @exception NamingException if the stub couldn't be found.
-     **/
-    private RMIServer findRMIServerJNDI(String jndiURL, Map<String, ?> env)
-            throws NamingException {
-
-        InitialContext ctx = new InitialContext(EnvHelp.mapToHashtable(env));
-
-        Object objref = ctx.lookup(jndiURL);
-        ctx.close();
-
-        return narrowJRMPServer(objref);
-    }
-
-    private static RMIServer narrowJRMPServer(Object objref) {
-
-        return (RMIServer) objref;
-    }
-
-    private RMIServer findRMIServerJRMP(String base64, Map<String, ?> env)
-        throws IOException {
-        final byte[] serialized;
-        try {
-            serialized = base64ToByteArray(base64);
-        } catch (IllegalArgumentException e) {
-            throw new MalformedURLException("Bad BASE64 encoding: " +
-                    e.getMessage());
-        }
-        final ByteArrayInputStream bin = new ByteArrayInputStream(serialized);
-
-        final ClassLoader loader = EnvHelp.resolveClientClassLoader(env);
-        final ObjectInputStream oin =
-                (loader == null) ?
-                    new ObjectInputStream(bin) :
-                    new ObjectInputStreamWithLoader(bin, loader);
-        final Object stub;
-        try {
-            stub = oin.readObject();
-        } catch (ClassNotFoundException e) {
-            throw new MalformedURLException("Class not found: " + e);
-        }
-        return (RMIServer)stub;
-    }
-
-    private static final class ObjectInputStreamWithLoader
-            extends ObjectInputStream {
-        ObjectInputStreamWithLoader(InputStream in, ClassLoader cl)
-        throws IOException, IllegalArgumentException {
-            super(in);
-            if (cl == null ) {
-              throw new IllegalArgumentException("class loader is null");
-            }
-            this.loader = cl;
-        }
-
-        @Override
-        protected Class<?> resolveClass(ObjectStreamClass classDesc)
-                throws IOException, ClassNotFoundException {
-            String name = classDesc.getName();
-            ReflectUtil.checkPackageAccess(name);
-            return Class.forName(name, false, Objects.requireNonNull(loader));
-        }
-
-        private final ClassLoader loader;
-    }
-
-    private MBeanServerConnection getConnectionWithSubject(Subject delegationSubject) {
-        MBeanServerConnection conn = null;
-
-        if (delegationSubject == null) {
-            if (nullSubjectConnRef == null
-                    || (conn = nullSubjectConnRef.get()) == null) {
-                conn = new RemoteMBeanServerConnection(null);
-                nullSubjectConnRef = new WeakReference<MBeanServerConnection>(conn);
-            }
-        } else {
-            WeakReference<MBeanServerConnection> wr = rmbscMap.get(delegationSubject);
-            if (wr == null || (conn = wr.get()) == null) {
-                conn = new RemoteMBeanServerConnection(delegationSubject);
-                rmbscMap.put(delegationSubject, new WeakReference<MBeanServerConnection>(conn));
-            }
-        }
-        return conn;
-    }
-
-    /*
-       The following section of code avoids a class loading problem
-       with RMI.  The problem is that an RMI stub, when deserializing
-       a remote method return value or exception, will first of all
-       consult the first non-bootstrap class loader it finds in the
-       call stack.  This can lead to behavior that is not portable
-       between implementations of the JMX Remote API.  Notably, an
-       implementation on J2SE 1.4 will find the RMI stub's loader on
-       the stack.  But in J2SE 5, this stub is loaded by the
-       bootstrap loader, so RMI will find the loader of the user code
-       that called an MBeanServerConnection method.
-
-       To avoid this problem, we take advantage of what the RMI stub
-       is doing internally.  Each remote call will end up calling
-       ref.invoke(...), where ref is the RemoteRef parameter given to
-       the RMI stub's constructor.  It is within this call that the
-       deserialization will happen.  So we fabricate our own RemoteRef
-       that delegates everything to the "real" one but that is loaded
-       by a class loader that knows no other classes.  The class
-       loader NoCallStackClassLoader does this: the RemoteRef is an
-       instance of the class named by proxyRefClassName, which is
-       fabricated by the class loader using byte code that is defined
-       by the string below.
-
-       The call stack when the deserialization happens is thus this:
-       MBeanServerConnection.getAttribute (or whatever)
-       -> RMIConnectionImpl_Stub.getAttribute
-          -> ProxyRef.invoke(...getAttribute...)
-             -> UnicastRef.invoke(...getAttribute...)
-                -> internal RMI stuff
-
-       Here UnicastRef is the RemoteRef created when the stub was
-       deserialized (which is of some RMI internal class).  It and the
-       "internal RMI stuff" are loaded by the bootstrap loader, so are
-       transparent to the stack search.  The first non-bootstrap
-       loader found is our ProxyRefLoader, as required.
-
-       In a future version of this code as integrated into J2SE 5,
-       this workaround could be replaced by direct access to the
-       internals of RMI.  For now, we use the same code base for J2SE
-       and for the standalone Reference Implementation.
-
-       The byte code below encodes the following class, compiled using
-       J2SE 1.4.2 with the -g:none option.
-
-        package com.sun.jmx.remote.internal;
-
-        import java.lang.reflect.Method;
-        import java.rmi.Remote;
-        import java.rmi.server.RemoteRef;
-        import com.sun.jmx.remote.internal.ProxyRef;
-
-        public class PRef extends ProxyRef {
-            public PRef(RemoteRef ref) {
-                super(ref);
-            }
-
-            public Object invoke(Remote obj, Method method,
-                                 Object[] params, long opnum)
-                    throws Exception {
-                return ref.invoke(obj, method, params, opnum);
-            }
-        }
-     */
-
-    private static final String rmiServerImplStubClassName =
-        RMIServer.class.getName() + "Impl_Stub";
-    private static final Class<?> rmiServerImplStubClass;
-    private static final String rmiConnectionImplStubClassName =
-            RMIConnection.class.getName() + "Impl_Stub";
-    private static final Class<?> rmiConnectionImplStubClass;
-    private static final String pRefClassName =
-        "jdk.jmx.remote.internal.PRef";
-    private static final Constructor<?> proxyRefConstructor;
-    static {
-        final String pRefByteCodeString =
-                "\312\376\272\276\0\0\0\60\0\27\12\0\5\0\15\11\0\4\0\16\13\0\17"+
-                "\0\20\7\0\21\7\0\22\1\0\6<init>\1\0\36(Ljava/rmi/server/Remote"+
-                "Ref;)V\1\0\4Code\1\0\6invoke\1\0S(Ljava/rmi/Remote;Ljava/lang/"+
-                "reflect/Method;[Ljava/lang/Object;J)Ljava/lang/Object;\1\0\12E"+
-                "xceptions\7\0\23\14\0\6\0\7\14\0\24\0\25\7\0\26\14\0\11\0\12\1"+
-                "\0\34jdk/jmx/remote/internal/PRef\1\0$com/sun/jmx/remote/inter"+
-                "nal/ProxyRef\1\0\23java/lang/Exception\1\0\3ref\1\0\33Ljava/rm"+
-                "i/server/RemoteRef;\1\0\31java/rmi/server/RemoteRef\0!\0\4\0\5"+
-                "\0\0\0\0\0\2\0\1\0\6\0\7\0\1\0\10\0\0\0\22\0\2\0\2\0\0\0\6*+\267"+
-                "\0\1\261\0\0\0\0\0\1\0\11\0\12\0\2\0\10\0\0\0\33\0\6\0\6\0\0\0"+
-                "\17*\264\0\2+,-\26\4\271\0\3\6\0\260\0\0\0\0\0\13\0\0\0\4\0\1\0"+
-                "\14\0\0";
-        final byte[] pRefByteCode =
-                NoCallStackClassLoader.stringToBytes(pRefByteCodeString);
-        PrivilegedExceptionAction<Constructor<?>> action =
-                new PrivilegedExceptionAction<Constructor<?>>() {
-            public Constructor<?> run() throws Exception {
-                Class<RMIConnector> thisClass = RMIConnector.class;
-                ClassLoader thisLoader = thisClass.getClassLoader();
-                ProtectionDomain thisProtectionDomain =
-                        thisClass.getProtectionDomain();
-
-                String proxyRefCName = ProxyRef.class.getName();
-                ClassLoader cl =
-                        new NoCallStackClassLoader(pRefClassName,
-                        pRefByteCode,
-                        new String[] { proxyRefCName },
-                        thisLoader,
-                        thisProtectionDomain);
-
-                Module jmxModule = ProxyRef.class.getModule();
-                Module rmiModule = RemoteRef.class.getModule();
-
-                String pkg = packageOf(pRefClassName);
-                assert pkg != null && pkg.length() > 0 && !pkg.equals(packageOf(proxyRefCName));
-                Module m = Modules.defineModule(cl, "jdk.remoteref", Collections.singleton(pkg));
-
-                // jdk.remoteref needs to read to java.base and jmxModule
-                Modules.addReads(m, Object.class.getModule());
-                Modules.addReads(m, jmxModule);
-                Modules.addReads(m, rmiModule);
-
-                // jdk.remoteref needs access to ProxyRef class
-                Modules.addExports(jmxModule, packageOf(proxyRefCName), m);
-
-                // java.management needs to instantiate the fabricated RemoteRef class
-                Modules.addReads(jmxModule, m);
-                Modules.addExports(m, pkg, jmxModule);
-
-                Class<?> c = cl.loadClass(pRefClassName);
-                return c.getConstructor(RemoteRef.class);
-            }
-        };
-
-        Class<?> serverStubClass;
-        try {
-            serverStubClass = Class.forName(rmiServerImplStubClassName);
-        } catch (Exception e) {
-            logger.error("<clinit>",
-                    "Failed to instantiate " +
-                    rmiServerImplStubClassName + ": " + e);
-            logger.debug("<clinit>",e);
-            serverStubClass = null;
-        }
-        rmiServerImplStubClass = serverStubClass;
-
-        Class<?> stubClass;
-        Constructor<?> constr;
-        try {
-            stubClass = Class.forName(rmiConnectionImplStubClassName);
-            constr = (Constructor<?>) AccessController.doPrivileged(action);
-        } catch (Exception e) {
-            logger.error("<clinit>",
-                    "Failed to initialize proxy reference constructor "+
-                    "for " + rmiConnectionImplStubClassName + ": " + e);
-            logger.debug("<clinit>",e);
-            stubClass = null;
-            constr = null;
-        }
-        rmiConnectionImplStubClass = stubClass;
-        proxyRefConstructor = constr;
-    }
-
-    private static String packageOf(String cn) {
-        int i = cn.lastIndexOf('.');
-        return i > 0 ? cn.substring(0, i) : "";
-    }
-
-    private static RMIConnection shadowJrmpStub(RemoteObject stub)
-    throws InstantiationException, IllegalAccessException,
-            InvocationTargetException, ClassNotFoundException,
-            NoSuchMethodException {
-        RemoteRef ref = stub.getRef();
-        RemoteRef proxyRef = (RemoteRef)
-            proxyRefConstructor.newInstance(new Object[] {ref});
-        final Constructor<?> rmiConnectionImplStubConstructor =
-            rmiConnectionImplStubClass.getConstructor(RemoteRef.class);
-        Object[] args = {proxyRef};
-        RMIConnection proxyStub = (RMIConnection)
-        rmiConnectionImplStubConstructor.newInstance(args);
-        return proxyStub;
-    }
-
-    private static RMIConnection getConnection(RMIServer server,
-            Object credentials,
-            boolean checkStub)
-            throws IOException {
-        RMIConnection c = server.newClient(credentials);
-        if (checkStub) checkStub(c, rmiConnectionImplStubClass);
-        try {
-            if (c.getClass() == rmiConnectionImplStubClass)
-                return shadowJrmpStub((RemoteObject) c);
-            logger.trace("getConnection",
-                    "Did not wrap " + c.getClass() + " to foil " +
-                    "stack search for classes: class loading semantics " +
-                    "may be incorrect");
-        } catch (Exception e) {
-            logger.error("getConnection",
-                    "Could not wrap " + c.getClass() + " to foil " +
-                    "stack search for classes: class loading semantics " +
-                    "may be incorrect: " + e);
-            logger.debug("getConnection",e);
-            // so just return the original stub, which will work for all
-            // but the most exotic class loading situations
-        }
-        return c;
-    }
-
-    private static byte[] base64ToByteArray(String s) {
-        int sLen = s.length();
-        int numGroups = sLen/4;
-        if (4*numGroups != sLen)
-            throw new IllegalArgumentException(
-                    "String length must be a multiple of four.");
-        int missingBytesInLastGroup = 0;
-        int numFullGroups = numGroups;
-        if (sLen != 0) {
-            if (s.charAt(sLen-1) == '=') {
-                missingBytesInLastGroup++;
-                numFullGroups--;
-            }
-            if (s.charAt(sLen-2) == '=')
-                missingBytesInLastGroup++;
-        }
-        byte[] result = new byte[3*numGroups - missingBytesInLastGroup];
-
-        // Translate all full groups from base64 to byte array elements
-        int inCursor = 0, outCursor = 0;
-        for (int i=0; i<numFullGroups; i++) {
-            int ch0 = base64toInt(s.charAt(inCursor++));
-            int ch1 = base64toInt(s.charAt(inCursor++));
-            int ch2 = base64toInt(s.charAt(inCursor++));
-            int ch3 = base64toInt(s.charAt(inCursor++));
-            result[outCursor++] = (byte) ((ch0 << 2) | (ch1 >> 4));
-            result[outCursor++] = (byte) ((ch1 << 4) | (ch2 >> 2));
-            result[outCursor++] = (byte) ((ch2 << 6) | ch3);
-        }
-
-        // Translate partial group, if present
-        if (missingBytesInLastGroup != 0) {
-            int ch0 = base64toInt(s.charAt(inCursor++));
-            int ch1 = base64toInt(s.charAt(inCursor++));
-            result[outCursor++] = (byte) ((ch0 << 2) | (ch1 >> 4));
-
-            if (missingBytesInLastGroup == 1) {
-                int ch2 = base64toInt(s.charAt(inCursor++));
-                result[outCursor++] = (byte) ((ch1 << 4) | (ch2 >> 2));
-            }
-        }
-        // assert inCursor == s.length()-missingBytesInLastGroup;
-        // assert outCursor == result.length;
-        return result;
-    }
-
-    /**
-     * Translates the specified character, which is assumed to be in the
-     * "Base 64 Alphabet" into its equivalent 6-bit positive integer.
-     *
-     * @throws IllegalArgumentException if
-     *        c is not in the Base64 Alphabet.
-     */
-    private static int base64toInt(char c) {
-        int result;
-
-        if (c >= base64ToInt.length)
-            result = -1;
-        else
-            result = base64ToInt[c];
-
-        if (result < 0)
-            throw new IllegalArgumentException("Illegal character " + c);
-        return result;
-    }
-
-    /**
-     * This array is a lookup table that translates unicode characters
-     * drawn from the "Base64 Alphabet" (as specified in Table 1 of RFC 2045)
-     * into their 6-bit positive integer equivalents.  Characters that
-     * are not in the Base64 alphabet but fall within the bounds of the
-     * array are translated to -1.
-     */
-    private static final byte base64ToInt[] = {
-        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-        -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54,
-        55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4,
-        5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
-        24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34,
-        35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
-    };
-
-    //--------------------------------------------------------------------
-    // Private stuff - Find / Set default class loader
-    //--------------------------------------------------------------------
-    private ClassLoader pushDefaultClassLoader() {
-        final Thread t = Thread.currentThread();
-        final ClassLoader old =  t.getContextClassLoader();
-        if (defaultClassLoader != null)
-            AccessController.doPrivileged(new PrivilegedAction<Void>() {
-                public Void run() {
-                    t.setContextClassLoader(defaultClassLoader);
-                    return null;
-                }
-            });
-            return old;
-    }
-
-    private void popDefaultClassLoader(final ClassLoader old) {
-        AccessController.doPrivileged(new PrivilegedAction<Void>() {
-            public Void run() {
-                Thread.currentThread().setContextClassLoader(old);
-                return null;
-            }
-        });
-    }
-
-    //--------------------------------------------------------------------
-    // Private variables
-    //--------------------------------------------------------------------
-    /**
-     * @serial The RMIServer stub of the RMI JMX Connector server to
-     * which this client connector is (or will be) connected. This
-     * field can be null when <var>jmxServiceURL</var> is not
-     * null. This includes the case where <var>jmxServiceURL</var>
-     * contains a serialized RMIServer stub. If both
-     * <var>rmiServer</var> and <var>jmxServiceURL</var> are null then
-     * serialization will fail.
-     *
-     * @see #RMIConnector(RMIServer,Map)
-     **/
-    private final RMIServer rmiServer;
-
-    /**
-     * @serial The JMXServiceURL of the RMI JMX Connector server to
-     * which this client connector will be connected. This field can
-     * be null when <var>rmiServer</var> is not null. If both
-     * <var>rmiServer</var> and <var>jmxServiceURL</var> are null then
-     * serialization will fail.
-     *
-     * @see #RMIConnector(JMXServiceURL,Map)
-     **/
-    private final JMXServiceURL jmxServiceURL;
-
-    // ---------------------------------------------------------
-    // WARNING - WARNING - WARNING - WARNING - WARNING - WARNING
-    // ---------------------------------------------------------
-    // Any transient variable which needs to be initialized should
-    // be initialized in the method initTransient()
-    private transient Map<String, Object> env;
-    private transient ClassLoader defaultClassLoader;
-    private transient RMIConnection connection;
-    private transient String connectionId;
-
-    private transient long clientNotifSeqNo = 0;
-
-    private transient WeakHashMap<Subject, WeakReference<MBeanServerConnection>> rmbscMap;
-    private transient WeakReference<MBeanServerConnection> nullSubjectConnRef = null;
-
-    private transient RMINotifClient rmiNotifClient;
-    // = new RMINotifClient(new Integer(0));
-
-    private transient long clientNotifCounter = 0;
-
-    private transient boolean connected;
-    // = false;
-    private transient boolean terminated;
-    // = false;
-
-    private transient Exception closeException;
-
-    private transient NotificationBroadcasterSupport connectionBroadcaster;
-
-    private transient ClientCommunicatorAdmin communicatorAdmin;
-
-    /**
-     * A static WeakReference to an {@link org.omg.CORBA.ORB ORB} to
-     * connect unconnected stubs.
-     **/
-    private static volatile WeakReference<Object> orb = null;
-
-    // TRACES & DEBUG
-    //---------------
-    private static String objects(final Object[] objs) {
-        if (objs == null)
-            return "null";
-        else
-            return Arrays.asList(objs).toString();
-    }
-
-    private static String strings(final String[] strs) {
-        return objects(strs);
-    }
-
-    static String getAttributesNames(AttributeList attributes) {
-        return attributes != null ?
-                attributes.asList().stream()
-                        .map(Attribute::getName)
-                        .collect(Collectors.joining(", ", "[", "]"))
-                : "[]";
-    }
-}
--- a/jdk/src/java.management/share/classes/javax/management/remote/rmi/RMIConnectorServer.java	Thu Feb 02 12:28:23 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,819 +0,0 @@
-/*
- * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package javax.management.remote.rmi;
-
-
-import com.sun.jmx.remote.security.MBeanServerFileAccessController;
-import com.sun.jmx.remote.util.ClassLogger;
-import com.sun.jmx.remote.util.EnvHelp;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.ObjectOutputStream;
-import java.net.MalformedURLException;
-import java.rmi.server.RMIClientSocketFactory;
-import java.rmi.server.RMIServerSocketFactory;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Hashtable;
-import java.util.Map;
-import java.util.Set;
-
-import javax.management.InstanceNotFoundException;
-import javax.management.MBeanServer;
-import javax.management.remote.JMXAuthenticator;
-
-import javax.management.remote.JMXConnectionNotification;
-import javax.management.remote.JMXConnector;
-import javax.management.remote.JMXConnectorServer;
-import javax.management.remote.JMXServiceURL;
-import javax.management.remote.MBeanServerForwarder;
-
-import javax.naming.InitialContext;
-import javax.naming.NamingException;
-
-/**
- * <p>A JMX API connector server that creates RMI-based connections
- * from remote clients.  Usually, such connector servers are made
- * using {@link javax.management.remote.JMXConnectorServerFactory
- * JMXConnectorServerFactory}.  However, specialized applications can
- * use this class directly, for example with an {@link RMIServerImpl}
- * object.</p>
- *
- * @since 1.5
- */
-public class RMIConnectorServer extends JMXConnectorServer {
-    /**
-     * <p>Name of the attribute that specifies whether the {@link
-     * RMIServer} stub that represents an RMI connector server should
-     * override an existing stub at the same address.  The value
-     * associated with this attribute, if any, should be a string that
-     * is equal, ignoring case, to <code>"true"</code> or
-     * <code>"false"</code>.  The default value is false.</p>
-     */
-    public static final String JNDI_REBIND_ATTRIBUTE =
-        "jmx.remote.jndi.rebind";
-
-    /**
-     * <p>Name of the attribute that specifies the {@link
-     * RMIClientSocketFactory} for the RMI objects created in
-     * conjunction with this connector. The value associated with this
-     * attribute must be of type <code>RMIClientSocketFactory</code> and can
-     * only be specified in the <code>Map</code> argument supplied when
-     * creating a connector server.</p>
-     */
-    public static final String RMI_CLIENT_SOCKET_FACTORY_ATTRIBUTE =
-        "jmx.remote.rmi.client.socket.factory";
-
-    /**
-     * <p>Name of the attribute that specifies the {@link
-     * RMIServerSocketFactory} for the RMI objects created in
-     * conjunction with this connector. The value associated with this
-     * attribute must be of type <code>RMIServerSocketFactory</code> and can
-     * only be specified in the <code>Map</code> argument supplied when
-     * creating a connector server.</p>
-     */
-    public static final String RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE =
-        "jmx.remote.rmi.server.socket.factory";
-
-    /**
-    * Name of the attribute that specifies a list of class names acceptable
-    * as parameters to the {@link RMIServer#newClient(java.lang.Object) RMIServer.newClient()}
-    * remote method call.
-    * <p>
-    * This list of classes should correspond to the transitive closure of the
-    * credentials class (or classes) used by the installed {@linkplain JMXAuthenticator}
-    * associated with the {@linkplain RMIServer} implementation.
-    * <p>
-    * If the attribute is not set, or is null, then any class is
-    * deemed acceptable.
-    */
-    public static final String CREDENTIAL_TYPES =
-            "jmx.remote.rmi.server.credential.types";
-
-    /**
-     * <p>Makes an <code>RMIConnectorServer</code>.
-     * This is equivalent to calling {@link #RMIConnectorServer(
-     * JMXServiceURL,Map,RMIServerImpl,MBeanServer)
-     * RMIConnectorServer(directoryURL,environment,null,null)}</p>
-     *
-     * @param url the URL defining how to create the connector server.
-     * Cannot be null.
-     *
-     * @param environment attributes governing the creation and
-     * storing of the RMI object.  Can be null, which is equivalent to
-     * an empty Map.
-     *
-     * @exception IllegalArgumentException if <code>url</code> is null.
-     *
-     * @exception MalformedURLException if <code>url</code> does not
-     * conform to the syntax for an RMI connector, or if its protocol
-     * is not recognized by this implementation. Only "rmi" is valid when
-     * this constructor is used.
-     *
-     * @exception IOException if the connector server cannot be created
-     * for some reason or if it is inevitable that its {@link #start()
-     * start} method will fail.
-     */
-    public RMIConnectorServer(JMXServiceURL url, Map<String,?> environment)
-            throws IOException {
-        this(url, environment, (MBeanServer) null);
-    }
-
-    /**
-     * <p>Makes an <code>RMIConnectorServer</code> for the given MBean
-     * server.
-     * This is equivalent to calling {@link #RMIConnectorServer(
-     * JMXServiceURL,Map,RMIServerImpl,MBeanServer)
-     * RMIConnectorServer(directoryURL,environment,null,mbeanServer)}</p>
-     *
-     * @param url the URL defining how to create the connector server.
-     * Cannot be null.
-     *
-     * @param environment attributes governing the creation and
-     * storing of the RMI object.  Can be null, which is equivalent to
-     * an empty Map.
-     *
-     * @param mbeanServer the MBean server to which the new connector
-     * server is attached, or null if it will be attached by being
-     * registered as an MBean in the MBean server.
-     *
-     * @exception IllegalArgumentException if <code>url</code> is null.
-     *
-     * @exception MalformedURLException if <code>url</code> does not
-     * conform to the syntax for an RMI connector, or if its protocol
-     * is not recognized by this implementation. Only "rmi" is valid
-     * when this constructor is used.
-     *
-     * @exception IOException if the connector server cannot be created
-     * for some reason or if it is inevitable that its {@link #start()
-     * start} method will fail.
-     */
-    public RMIConnectorServer(JMXServiceURL url, Map<String,?> environment,
-                              MBeanServer mbeanServer)
-            throws IOException {
-        this(url, environment, (RMIServerImpl) null, mbeanServer);
-    }
-
-    /**
-     * <p>Makes an <code>RMIConnectorServer</code> for the given MBean
-     * server.</p>
-     *
-     * @param url the URL defining how to create the connector server.
-     * Cannot be null.
-     *
-     * @param environment attributes governing the creation and
-     * storing of the RMI object.  Can be null, which is equivalent to
-     * an empty Map.
-     *
-     * @param rmiServerImpl An implementation of the RMIServer interface,
-     *  consistent with the protocol type specified in <var>url</var>.
-     *  If this parameter is non null, the protocol type specified by
-     *  <var>url</var> is not constrained, and is assumed to be valid.
-     *  Otherwise, only "rmi" will be recognized.
-     *
-     * @param mbeanServer the MBean server to which the new connector
-     * server is attached, or null if it will be attached by being
-     * registered as an MBean in the MBean server.
-     *
-     * @exception IllegalArgumentException if <code>url</code> is null.
-     *
-     * @exception MalformedURLException if <code>url</code> does not
-     * conform to the syntax for an RMI connector, or if its protocol
-     * is not recognized by this implementation. Only "rmi" is recognized
-     * when <var>rmiServerImpl</var> is null.
-     *
-     * @exception IOException if the connector server cannot be created
-     * for some reason or if it is inevitable that its {@link #start()
-     * start} method will fail.
-     *
-     * @see #start
-     */
-    public RMIConnectorServer(JMXServiceURL url, Map<String,?> environment,
-                              RMIServerImpl rmiServerImpl,
-                              MBeanServer mbeanServer)
-            throws IOException {
-        super(mbeanServer);
-
-        if (url == null) throw new
-            IllegalArgumentException("Null JMXServiceURL");
-        if (rmiServerImpl == null) {
-            final String prt = url.getProtocol();
-            if (prt == null || !(prt.equals("rmi"))) {
-                final String msg = "Invalid protocol type: " + prt;
-                throw new MalformedURLException(msg);
-            }
-            final String urlPath = url.getURLPath();
-            if (!urlPath.equals("")
-                && !urlPath.equals("/")
-                && !urlPath.startsWith("/jndi/")) {
-                final String msg = "URL path must be empty or start with " +
-                    "/jndi/";
-                throw new MalformedURLException(msg);
-            }
-        }
-
-        if (environment == null)
-            this.attributes = Collections.emptyMap();
-        else {
-            EnvHelp.checkAttributes(environment);
-            this.attributes = Collections.unmodifiableMap(environment);
-        }
-
-        this.address = url;
-        this.rmiServerImpl = rmiServerImpl;
-    }
-
-    /**
-     * <p>Returns a client stub for this connector server.  A client
-     * stub is a serializable object whose {@link
-     * JMXConnector#connect(Map) connect} method can be used to make
-     * one new connection to this connector server.</p>
-     *
-     * @param env client connection parameters of the same sort that
-     * could be provided to {@link JMXConnector#connect(Map)
-     * JMXConnector.connect(Map)}.  Can be null, which is equivalent
-     * to an empty map.
-     *
-     * @return a client stub that can be used to make a new connection
-     * to this connector server.
-     *
-     * @exception UnsupportedOperationException if this connector
-     * server does not support the generation of client stubs.
-     *
-     * @exception IllegalStateException if the JMXConnectorServer is
-     * not started (see {@link #isActive()}).
-     *
-     * @exception IOException if a communications problem means that a
-     * stub cannot be created.
-     **/
-    public JMXConnector toJMXConnector(Map<String,?> env) throws IOException {
-        // The serialized for of rmiServerImpl is automatically
-        // a RMI server stub.
-        if (!isActive()) throw new
-            IllegalStateException("Connector is not active");
-
-        // Merge maps
-        Map<String, Object> usemap = new HashMap<String, Object>(
-                (this.attributes==null)?Collections.<String, Object>emptyMap():
-                    this.attributes);
-
-        if (env != null) {
-            EnvHelp.checkAttributes(env);
-            usemap.putAll(env);
-        }
-
-        usemap = EnvHelp.filterAttributes(usemap);
-
-        final RMIServer stub=(RMIServer)rmiServerImpl.toStub();
-
-        return new RMIConnector(stub, usemap);
-    }
-
-    /**
-     * <p>Activates the connector server, that is starts listening for
-     * client connections.  Calling this method when the connector
-     * server is already active has no effect.  Calling this method
-     * when the connector server has been stopped will generate an
-     * <code>IOException</code>.</p>
-     *
-     * <p>The behavior of this method when called for the first time
-     * depends on the parameters that were supplied at construction,
-     * as described below.</p>
-     *
-     * <p>First, an object of a subclass of {@link RMIServerImpl} is
-     * required, to export the connector server through RMI:</p>
-     *
-     * <ul>
-     *
-     * <li>If an <code>RMIServerImpl</code> was supplied to the
-     * constructor, it is used.
-     *
-     * <li>Otherwise, if the <code>JMXServiceURL</code>
-     * was null, or its protocol part was <code>rmi</code>, an object
-     * of type {@link RMIJRMPServerImpl} is created.
-     *
-     * <li>Otherwise, the implementation can create an
-     * implementation-specific {@link RMIServerImpl} or it can throw
-     * {@link MalformedURLException}.
-     *
-     * </ul>
-     *
-     * <p>If the given address includes a JNDI directory URL as
-     * specified in the package documentation for {@link
-     * javax.management.remote.rmi}, then this
-     * <code>RMIConnectorServer</code> will bootstrap by binding the
-     * <code>RMIServerImpl</code> to the given address.</p>
-     *
-     * <p>If the URL path part of the <code>JMXServiceURL</code> was
-     * empty or a single slash (<code>/</code>), then the RMI object
-     * will not be bound to a directory.  Instead, a reference to it
-     * will be encoded in the URL path of the RMIConnectorServer
-     * address (returned by {@link #getAddress()}).  The encodings for
-     * <code>rmi</code> are described in the package documentation for
-     * {@link javax.management.remote.rmi}.</p>
-     *
-     * <p>The behavior when the URL path is neither empty nor a JNDI
-     * directory URL, or when the protocol is not <code>rmi</code>,
-     * is implementation defined, and may include throwing
-     * {@link MalformedURLException} when the connector server is created
-     * or when it is started.</p>
-     *
-     * @exception IllegalStateException if the connector server has
-     * not been attached to an MBean server.
-     * @exception IOException if the connector server cannot be
-     * started.
-     */
-    public synchronized void start() throws IOException {
-        final boolean tracing = logger.traceOn();
-
-        if (state == STARTED) {
-            if (tracing) logger.trace("start", "already started");
-            return;
-        } else if (state == STOPPED) {
-            if (tracing) logger.trace("start", "already stopped");
-            throw new IOException("The server has been stopped.");
-        }
-
-        if (getMBeanServer() == null)
-            throw new IllegalStateException("This connector server is not " +
-                                            "attached to an MBean server");
-
-        // Check the internal access file property to see
-        // if an MBeanServerForwarder is to be provided
-        //
-        if (attributes != null) {
-            // Check if access file property is specified
-            //
-            String accessFile =
-                (String) attributes.get("jmx.remote.x.access.file");
-            if (accessFile != null) {
-                // Access file property specified, create an instance
-                // of the MBeanServerFileAccessController class
-                //
-                MBeanServerForwarder mbsf;
-                try {
-                    mbsf = new MBeanServerFileAccessController(accessFile);
-                } catch (IOException e) {
-                    throw EnvHelp.initCause(
-                        new IllegalArgumentException(e.getMessage()), e);
-                }
-                // Set the MBeanServerForwarder
-                //
-                setMBeanServerForwarder(mbsf);
-            }
-        }
-
-        try {
-            if (tracing) logger.trace("start", "setting default class loader");
-            defaultClassLoader = EnvHelp.resolveServerClassLoader(
-                    attributes, getMBeanServer());
-        } catch (InstanceNotFoundException infc) {
-            IllegalArgumentException x = new
-                IllegalArgumentException("ClassLoader not found: "+infc);
-            throw EnvHelp.initCause(x,infc);
-        }
-
-        if (tracing) logger.trace("start", "setting RMIServer object");
-        final RMIServerImpl rmiServer;
-
-        if (rmiServerImpl != null)
-            rmiServer = rmiServerImpl;
-        else
-            rmiServer = newServer();
-
-        rmiServer.setMBeanServer(getMBeanServer());
-        rmiServer.setDefaultClassLoader(defaultClassLoader);
-        rmiServer.setRMIConnectorServer(this);
-        rmiServer.export();
-
-        try {
-            if (tracing) logger.trace("start", "getting RMIServer object to export");
-            final RMIServer objref = objectToBind(rmiServer, attributes);
-
-            if (address != null && address.getURLPath().startsWith("/jndi/")) {
-                final String jndiUrl = address.getURLPath().substring(6);
-
-                if (tracing)
-                    logger.trace("start", "Using external directory: " + jndiUrl);
-
-                String stringBoolean = (String) attributes.get(JNDI_REBIND_ATTRIBUTE);
-                final boolean rebind = EnvHelp.computeBooleanFromString( stringBoolean );
-
-                if (tracing)
-                    logger.trace("start", JNDI_REBIND_ATTRIBUTE + "=" + rebind);
-
-                try {
-                    if (tracing) logger.trace("start", "binding to " + jndiUrl);
-
-                    final Hashtable<?, ?> usemap = EnvHelp.mapToHashtable(attributes);
-
-                    bind(jndiUrl, usemap, objref, rebind);
-
-                    boundJndiUrl = jndiUrl;
-                } catch (NamingException e) {
-                    // fit e in the nested exception if we are on 1.4
-                    throw newIOException("Cannot bind to URL ["+jndiUrl+"]: "
-                                         + e, e);
-                }
-            } else {
-                // if jndiURL is null, we must encode the stub into the URL.
-                if (tracing) logger.trace("start", "Encoding URL");
-
-                encodeStubInAddress(objref, attributes);
-
-                if (tracing) logger.trace("start", "Encoded URL: " + this.address);
-            }
-        } catch (Exception e) {
-            try {
-                rmiServer.close();
-            } catch (Exception x) {
-                // OK: we are already throwing another exception
-            }
-            if (e instanceof RuntimeException)
-                throw (RuntimeException) e;
-            else if (e instanceof IOException)
-                throw (IOException) e;
-            else
-                throw newIOException("Got unexpected exception while " +
-                                     "starting the connector server: "
-                                     + e, e);
-        }
-
-        rmiServerImpl = rmiServer;
-
-        synchronized(openedServers) {
-            openedServers.add(this);
-        }
-
-        state = STARTED;
-
-        if (tracing) {
-            logger.trace("start", "Connector Server Address = " + address);
-            logger.trace("start", "started.");
-        }
-    }
-
-    /**
-     * <p>Deactivates the connector server, that is, stops listening for
-     * client connections.  Calling this method will also close all
-     * client connections that were made by this server.  After this
-     * method returns, whether normally or with an exception, the
-     * connector server will not create any new client
-     * connections.</p>
-     *
-     * <p>Once a connector server has been stopped, it cannot be started
-     * again.</p>
-     *
-     * <p>Calling this method when the connector server has already
-     * been stopped has no effect.  Calling this method when the
-     * connector server has not yet been started will disable the
-     * connector server object permanently.</p>
-     *
-     * <p>If closing a client connection produces an exception, that
-     * exception is not thrown from this method.  A {@link
-     * JMXConnectionNotification} is emitted from this MBean with the
-     * connection ID of the connection that could not be closed.</p>
-     *
-     * <p>Closing a connector server is a potentially slow operation.
-     * For example, if a client machine with an open connection has
-     * crashed, the close operation might have to wait for a network
-     * protocol timeout.  Callers that do not want to block in a close
-     * operation should do it in a separate thread.</p>
-     *
-     * <p>This method calls the method {@link RMIServerImpl#close()
-     * close} on the connector server's <code>RMIServerImpl</code>
-     * object.</p>
-     *
-     * <p>If the <code>RMIServerImpl</code> was bound to a JNDI
-     * directory by the {@link #start() start} method, it is unbound
-     * from the directory by this method.</p>
-     *
-     * @exception IOException if the server cannot be closed cleanly,
-     * or if the <code>RMIServerImpl</code> cannot be unbound from the
-     * directory.  When this exception is thrown, the server has
-     * already attempted to close all client connections, if
-     * appropriate; to call {@link RMIServerImpl#close()}; and to
-     * unbind the <code>RMIServerImpl</code> from its directory, if
-     * appropriate.  All client connections are closed except possibly
-     * those that generated exceptions when the server attempted to
-     * close them.
-     */
-    public void stop() throws IOException {
-        final boolean tracing = logger.traceOn();
-
-        synchronized (this) {
-            if (state == STOPPED) {
-                if (tracing) logger.trace("stop","already stopped.");
-                return;
-            } else if (state == CREATED) {
-                if (tracing) logger.trace("stop","not started yet.");
-            }
-
-            if (tracing) logger.trace("stop", "stopping.");
-            state = STOPPED;
-        }
-
-        synchronized(openedServers) {
-            openedServers.remove(this);
-        }
-
-        IOException exception = null;
-
-        // rmiServerImpl can be null if stop() called without start()
-        if (rmiServerImpl != null) {
-            try {
-                if (tracing) logger.trace("stop", "closing RMI server.");
-                rmiServerImpl.close();
-            } catch (IOException e) {
-                if (tracing) logger.trace("stop", "failed to close RMI server: " + e);
-                if (logger.debugOn()) logger.debug("stop",e);
-                exception = e;
-            }
-        }
-
-        if (boundJndiUrl != null) {
-            try {
-                if (tracing)
-                    logger.trace("stop",
-                          "unbind from external directory: " + boundJndiUrl);
-
-                final Hashtable<?, ?> usemap = EnvHelp.mapToHashtable(attributes);
-
-                InitialContext ctx =
-                    new InitialContext(usemap);
-
-                ctx.unbind(boundJndiUrl);
-
-                ctx.close();
-            } catch (NamingException e) {
-                if (tracing) logger.trace("stop", "failed to unbind RMI server: "+e);
-                if (logger.debugOn()) logger.debug("stop",e);
-                // fit e in as the nested exception if we are on 1.4
-                if (exception == null)
-                    exception = newIOException("Cannot bind to URL: " + e, e);
-            }
-        }
-
-        if (exception != null) throw exception;
-
-        if (tracing) logger.trace("stop", "stopped");
-    }
-
-    public synchronized boolean isActive() {
-        return (state == STARTED);
-    }
-
-    public JMXServiceURL getAddress() {
-        if (!isActive())
-            return null;
-        return address;
-    }
-
-    public Map<String,?> getAttributes() {
-        Map<String, ?> map = EnvHelp.filterAttributes(attributes);
-        return Collections.unmodifiableMap(map);
-    }
-
-    @Override
-    public synchronized
-        void setMBeanServerForwarder(MBeanServerForwarder mbsf) {
-        super.setMBeanServerForwarder(mbsf);
-        if (rmiServerImpl != null)
-            rmiServerImpl.setMBeanServer(getMBeanServer());
-    }
-
-    /* We repeat the definitions of connection{Opened,Closed,Failed}
-       here so that they are accessible to other classes in this package
-       even though they have protected access.  */
-
-    @Override
-    protected void connectionOpened(String connectionId, String message,
-                                    Object userData) {
-        super.connectionOpened(connectionId, message, userData);
-    }
-
-    @Override
-    protected void connectionClosed(String connectionId, String message,
-                                    Object userData) {
-        super.connectionClosed(connectionId, message, userData);
-    }
-
-    @Override
-    protected void connectionFailed(String connectionId, String message,
-                                    Object userData) {
-        super.connectionFailed(connectionId, message, userData);
-    }
-
-    /**
-     * Bind a stub to a registry.
-     * @param jndiUrl URL of the stub in the registry, extracted
-     *        from the <code>JMXServiceURL</code>.
-     * @param attributes A Hashtable containing environment parameters,
-     *        built from the Map specified at this object creation.
-     * @param rmiServer The object to bind in the registry
-     * @param rebind true if the object must be rebound.
-     **/
-    void bind(String jndiUrl, Hashtable<?, ?> attributes,
-              RMIServer rmiServer, boolean rebind)
-        throws NamingException, MalformedURLException {
-        // if jndiURL is not null, we nust bind the stub to a
-        // directory.
-        InitialContext ctx =
-            new InitialContext(attributes);
-
-        if (rebind)
-            ctx.rebind(jndiUrl, rmiServer);
-        else
-            ctx.bind(jndiUrl, rmiServer);
-        ctx.close();
-    }
-
-    /**
-     * Creates a new RMIServerImpl.
-     **/
-    RMIServerImpl newServer() throws IOException {
-        final int port;
-        if (address == null)
-            port = 0;
-        else
-            port = address.getPort();
-
-        return newJRMPServer(attributes, port);
-    }
-
-    /**
-     * Encode a stub into the JMXServiceURL.
-     * @param rmiServer The stub object to encode in the URL
-     * @param attributes A Map containing environment parameters,
-     *        built from the Map specified at this object creation.
-     **/
-    private void encodeStubInAddress(
-            RMIServer rmiServer, Map<String, ?> attributes)
-            throws IOException {
-
-        final String protocol, host;
-        final int port;
-
-        if (address == null) {
-            protocol = "rmi";
-            host = null; // will default to local host name
-            port = 0;
-        } else {
-            protocol = address.getProtocol();
-            host = (address.getHost().equals("")) ? null : address.getHost();
-            port = address.getPort();
-        }
-
-        final String urlPath = encodeStub(rmiServer, attributes);
-
-        address = new JMXServiceURL(protocol, host, port, urlPath);
-    }
-
-    /**
-     * Returns the IOR of the given rmiServer.
-     **/
-    static String encodeStub(
-            RMIServer rmiServer, Map<String, ?> env) throws IOException {
-        return "/stub/" + encodeJRMPStub(rmiServer, env);
-    }
-
-    static String encodeJRMPStub(
-            RMIServer rmiServer, Map<String, ?> env)
-            throws IOException {
-        ByteArrayOutputStream bout = new ByteArrayOutputStream();
-        ObjectOutputStream oout = new ObjectOutputStream(bout);
-        oout.writeObject(rmiServer);
-        oout.close();
-        byte[] bytes = bout.toByteArray();
-        return byteArrayToBase64(bytes);
-    }
-
-    /**
-     * Object that we will bind to the registry.
-     * This object is a stub connected to our RMIServerImpl.
-     **/
-    private static RMIServer objectToBind(
-            RMIServerImpl rmiServer, Map<String, ?> env)
-        throws IOException {
-        return (RMIServer)rmiServer.toStub();
-    }
-
-    private static RMIServerImpl newJRMPServer(Map<String, ?> env, int port)
-            throws IOException {
-        RMIClientSocketFactory csf = (RMIClientSocketFactory)
-            env.get(RMI_CLIENT_SOCKET_FACTORY_ATTRIBUTE);
-        RMIServerSocketFactory ssf = (RMIServerSocketFactory)
-            env.get(RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE);
-        return new RMIJRMPServerImpl(port, csf, ssf, env);
-    }
-
-    private static String byteArrayToBase64(byte[] a) {
-        int aLen = a.length;
-        int numFullGroups = aLen/3;
-        int numBytesInPartialGroup = aLen - 3*numFullGroups;
-        int resultLen = 4*((aLen + 2)/3);
-        final StringBuilder result = new StringBuilder(resultLen);
-
-        // Translate all full groups from byte array elements to Base64
-        int inCursor = 0;
-        for (int i=0; i<numFullGroups; i++) {
-            int byte0 = a[inCursor++] & 0xff;
-            int byte1 = a[inCursor++] & 0xff;
-            int byte2 = a[inCursor++] & 0xff;
-            result.append(intToAlpha[byte0 >> 2]);
-            result.append(intToAlpha[(byte0 << 4)&0x3f | (byte1 >> 4)]);
-            result.append(intToAlpha[(byte1 << 2)&0x3f | (byte2 >> 6)]);
-            result.append(intToAlpha[byte2 & 0x3f]);
-        }
-
-        // Translate partial group if present
-        if (numBytesInPartialGroup != 0) {
-            int byte0 = a[inCursor++] & 0xff;
-            result.append(intToAlpha[byte0 >> 2]);
-            if (numBytesInPartialGroup == 1) {
-                result.append(intToAlpha[(byte0 << 4) & 0x3f]);
-                result.append("==");
-            } else {
-                // assert numBytesInPartialGroup == 2;
-                int byte1 = a[inCursor++] & 0xff;
-                result.append(intToAlpha[(byte0 << 4)&0x3f | (byte1 >> 4)]);
-                result.append(intToAlpha[(byte1 << 2)&0x3f]);
-                result.append('=');
-            }
-        }
-        // assert inCursor == a.length;
-        // assert result.length() == resultLen;
-        return result.toString();
-    }
-
-    /**
-     * This array is a lookup table that translates 6-bit positive integer
-     * index values into their "Base64 Alphabet" equivalents as specified
-     * in Table 1 of RFC 2045.
-     */
-    private static final char intToAlpha[] = {
-        'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
-        'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
-        'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
-        'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
-        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
-    };
-
-    /**
-     * Construct a new IOException with a nested exception.
-     * The nested exception is set only if JDK {@literal >= 1.4}
-     */
-    private static IOException newIOException(String message,
-                                              Throwable cause) {
-        final IOException x = new IOException(message);
-        return EnvHelp.initCause(x,cause);
-    }
-
-
-    // Private variables
-    // -----------------
-
-    private static ClassLogger logger =
-        new ClassLogger("javax.management.remote.rmi", "RMIConnectorServer");
-
-    private JMXServiceURL address;
-    private RMIServerImpl rmiServerImpl;
-    private final Map<String, ?> attributes;
-    private ClassLoader defaultClassLoader = null;
-
-    private String boundJndiUrl;
-
-    // state
-    private static final int CREATED = 0;
-    private static final int STARTED = 1;
-    private static final int STOPPED = 2;
-
-    private int state = CREATED;
-    private final static Set<RMIConnectorServer> openedServers =
-            new HashSet<RMIConnectorServer>();
-}
--- a/jdk/src/java.management/share/classes/javax/management/remote/rmi/RMIIIOPServerImpl.java	Thu Feb 02 12:28:23 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,96 +0,0 @@
-/*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package javax.management.remote.rmi;
-
-import java.io.IOException;
-import java.rmi.Remote;
-import java.util.Map;
-import javax.security.auth.Subject;
-
-/**
- * <p>An {@link RMIServerImpl} that is exported through IIOP and that
- * creates client connections as RMI objects exported through IIOP.
- * User code does not usually reference this class directly.</p>
- *
- * @see RMIServerImpl
- *
- * @since 1.5
- * @deprecated This transport is no longer supported.
- */
-@Deprecated
-public class RMIIIOPServerImpl extends RMIServerImpl {
-    /**
-     * Throws {@linkplain UnsupportedOperationException}
-     *
-     * @param env the environment containing attributes for the new
-     * <code>RMIServerImpl</code>.  Can be null, which is equivalent
-     * to an empty Map.
-     *
-     * @throws IOException if the RMI object cannot be created.
-     */
-    public RMIIIOPServerImpl(Map<String,?> env)
-            throws IOException {
-        super(env);
-
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    protected void export() throws IOException {
-        throw new UnsupportedOperationException("Method not supported. JMX RMI-IIOP is deprecated");
-    }
-
-    @Override
-    protected String getProtocol() {
-        return "iiop";
-    }
-
-    @Override
-    public Remote toStub() throws IOException {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    protected RMIConnection makeClient(String connectionId, Subject subject)
-            throws IOException {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    protected void closeClient(RMIConnection client) throws IOException {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    protected void closeServer() throws IOException {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    RMIConnection doNewClient(final Object credentials) throws IOException {
-        throw new UnsupportedOperationException();
-    }
-}
--- a/jdk/src/java.management/share/classes/javax/management/remote/rmi/RMIJRMPServerImpl.java	Thu Feb 02 12:28:23 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,279 +0,0 @@
-/*
- * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package javax.management.remote.rmi;
-
-import java.io.IOException;
-import java.rmi.NoSuchObjectException;
-import java.rmi.Remote;
-import java.rmi.RemoteException;
-import java.rmi.server.RMIClientSocketFactory;
-import java.rmi.server.RMIServerSocketFactory;
-import java.rmi.server.UnicastRemoteObject;
-import java.rmi.server.RemoteObject;
-import java.util.Map;
-import java.util.Collections;
-import javax.security.auth.Subject;
-
-import com.sun.jmx.remote.internal.RMIExporter;
-import com.sun.jmx.remote.util.EnvHelp;
-import java.io.ObjectStreamClass;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import sun.reflect.misc.ReflectUtil;
-import sun.rmi.server.DeserializationChecker;
-import sun.rmi.server.UnicastServerRef;
-import sun.rmi.server.UnicastServerRef2;
-
-/**
- * <p>An {@link RMIServer} object that is exported through JRMP and that
- * creates client connections as RMI objects exported through JRMP.
- * User code does not usually reference this class directly.</p>
- *
- * @see RMIServerImpl
- *
- * @since 1.5
- */
-public class RMIJRMPServerImpl extends RMIServerImpl {
-
-    private final ExportedWrapper exportedWrapper;
-
-    /**
-     * <p>Creates a new {@link RMIServer} object that will be exported
-     * on the given port using the given socket factories.</p>
-     *
-     * @param port the port on which this object and the {@link
-     * RMIConnectionImpl} objects it creates will be exported.  Can be
-     * zero, to indicate any available port.
-     *
-     * @param csf the client socket factory for the created RMI
-     * objects.  Can be null.
-     *
-     * @param ssf the server socket factory for the created RMI
-     * objects.  Can be null.
-     *
-     * @param env the environment map.  Can be null.
-     *
-     * @exception IOException if the {@link RMIServer} object
-     * cannot be created.
-     *
-     * @exception IllegalArgumentException if <code>port</code> is
-     * negative.
-     */
-    public RMIJRMPServerImpl(int port,
-                             RMIClientSocketFactory csf,
-                             RMIServerSocketFactory ssf,
-                             Map<String,?> env)
-            throws IOException {
-
-        super(env);
-
-        if (port < 0)
-            throw new IllegalArgumentException("Negative port: " + port);
-
-        this.port = port;
-        this.csf = csf;
-        this.ssf = ssf;
-        this.env = (env == null) ? Collections.<String, Object>emptyMap() : env;
-
-        String[] credentialsTypes
-                = (String[]) this.env.get(RMIConnectorServer.CREDENTIAL_TYPES);
-        List<String> types = null;
-        if (credentialsTypes != null) {
-            types = new ArrayList<>();
-            for (String type : credentialsTypes) {
-                if (type == null) {
-                    throw new IllegalArgumentException("A credential type is null.");
-                }
-                ReflectUtil.checkPackageAccess(type);
-                types.add(type);
-            }
-        }
-        exportedWrapper = types != null ?
-                new ExportedWrapper(this, types) :
-                null;
-    }
-
-    protected void export() throws IOException {
-        if (exportedWrapper != null) {
-            export(exportedWrapper);
-        } else {
-            export(this);
-        }
-    }
-
-    private void export(Remote obj) throws RemoteException {
-        final RMIExporter exporter =
-            (RMIExporter) env.get(RMIExporter.EXPORTER_ATTRIBUTE);
-        final boolean daemon = EnvHelp.isServerDaemon(env);
-
-        if (daemon && exporter != null) {
-            throw new IllegalArgumentException("If "+EnvHelp.JMX_SERVER_DAEMON+
-                    " is specified as true, "+RMIExporter.EXPORTER_ATTRIBUTE+
-                    " cannot be used to specify an exporter!");
-        }
-
-        if (daemon) {
-            if (csf == null && ssf == null) {
-                new UnicastServerRef(port).exportObject(obj, null, true);
-            } else {
-                new UnicastServerRef2(port, csf, ssf).exportObject(obj, null, true);
-            }
-        } else if (exporter != null) {
-            exporter.exportObject(obj, port, csf, ssf);
-        } else {
-            UnicastRemoteObject.exportObject(obj, port, csf, ssf);
-        }
-    }
-
-    private void unexport(Remote obj, boolean force)
-            throws NoSuchObjectException {
-        RMIExporter exporter =
-            (RMIExporter) env.get(RMIExporter.EXPORTER_ATTRIBUTE);
-        if (exporter == null)
-            UnicastRemoteObject.unexportObject(obj, force);
-        else
-            exporter.unexportObject(obj, force);
-    }
-
-    protected String getProtocol() {
-        return "rmi";
-    }
-
-    /**
-     * <p>Returns a serializable stub for this {@link RMIServer} object.</p>
-     *
-     * @return a serializable stub.
-     *
-     * @exception IOException if the stub cannot be obtained - e.g the
-     *            RMIJRMPServerImpl has not been exported yet.
-     */
-    public Remote toStub() throws IOException {
-        if (exportedWrapper != null) {
-            return RemoteObject.toStub(exportedWrapper);
-        } else {
-            return RemoteObject.toStub(this);
-        }
-    }
-
-    /**
-     * <p>Creates a new client connection as an RMI object exported
-     * through JRMP. The port and socket factories for the new
-     * {@link RMIConnection} object are the ones supplied
-     * to the <code>RMIJRMPServerImpl</code> constructor.</p>
-     *
-     * @param connectionId the ID of the new connection. Every
-     * connection opened by this connector server will have a
-     * different id.  The behavior is unspecified if this parameter is
-     * null.
-     *
-     * @param subject the authenticated subject.  Can be null.
-     *
-     * @return the newly-created <code>RMIConnection</code>.
-     *
-     * @exception IOException if the new {@link RMIConnection}
-     * object cannot be created or exported.
-     */
-    protected RMIConnection makeClient(String connectionId, Subject subject)
-            throws IOException {
-
-        if (connectionId == null)
-            throw new NullPointerException("Null connectionId");
-
-        RMIConnection client =
-            new RMIConnectionImpl(this, connectionId, getDefaultClassLoader(),
-                                  subject, env);
-        export(client);
-        return client;
-    }
-
-    protected void closeClient(RMIConnection client) throws IOException {
-        unexport(client, true);
-    }
-
-    /**
-     * <p>Called by {@link #close()} to close the connector server by
-     * unexporting this object.  After returning from this method, the
-     * connector server must not accept any new connections.</p>
-     *
-     * @exception IOException if the attempt to close the connector
-     * server failed.
-     */
-    protected void closeServer() throws IOException {
-        if (exportedWrapper != null) {
-            unexport(exportedWrapper, true);
-        } else {
-            unexport(this, true);
-        }
-    }
-
-    private final int port;
-    private final RMIClientSocketFactory csf;
-    private final RMIServerSocketFactory ssf;
-    private final Map<String, ?> env;
-
-    private static class ExportedWrapper implements RMIServer, DeserializationChecker {
-        private final RMIServer impl;
-        private final List<String> allowedTypes;
-
-        private ExportedWrapper(RMIServer impl, List<String> credentialsTypes) {
-            this.impl = impl;
-            allowedTypes = credentialsTypes;
-        }
-
-        @Override
-        public String getVersion() throws RemoteException {
-            return impl.getVersion();
-        }
-
-        @Override
-        public RMIConnection newClient(Object credentials) throws IOException {
-            return impl.newClient(credentials);
-        }
-
-        @Override
-        public void check(Method method, ObjectStreamClass descriptor,
-                int paramIndex, int callID) {
-            String type = descriptor.getName();
-            if (!allowedTypes.contains(type)) {
-                throw new ClassCastException("Unsupported type: " + type);
-            }
-        }
-
-        @Override
-        public void checkProxyClass(Method method, String[] ifaces,
-                int paramIndex, int callID) {
-            if (ifaces != null && ifaces.length > 0) {
-                for (String iface : ifaces) {
-                    if (!allowedTypes.contains(iface)) {
-                        throw new ClassCastException("Unsupported type: " + iface);
-                    }
-                }
-            }
-        }
-    }
-}
--- a/jdk/src/java.management/share/classes/javax/management/remote/rmi/RMIServer.java	Thu Feb 02 12:28:23 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,91 +0,0 @@
-/*
- * Copyright (c) 2002, 2007, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package javax.management.remote.rmi;
-
-import java.io.IOException;
-import java.rmi.Remote;
-import java.rmi.RemoteException;
-
-/**
- * <p>RMI object used to establish connections to an RMI connector.
- * There is one Remote object implementing this interface for each RMI
- * connector.</p>
- *
- * <p>User code does not usually refer to this interface.  It is
- * specified as part of the public API so that different
- * implementations of that API will interoperate.</p>
- *
- * @since 1.5
- */
-public interface RMIServer extends Remote {
-    /**
-     * <p>The version of the RMI Connector Protocol understood by this
-     * connector server.  This is a string with the following format:</p>
-     *
-     * <pre>
-     * <em>protocol-version</em> <em>implementation-name</em>
-     * </pre>
-     *
-     * <p>The <code><em>protocol-version</em></code> is a series of
-     * two or more non-negative integers separated by periods
-     * (<code>.</code>).  An implementation of the version described
-     * by this documentation must use the string <code>1.0</code>
-     * here.</p>
-     *
-     * <p>After the protocol version there must be a space, followed
-     * by the implementation name.  The format of the implementation
-     * name is unspecified.  It is recommended that it include an
-     * implementation version number.  An implementation can use an
-     * empty string as its implementation name, for example for
-     * security reasons.</p>
-     *
-     * @return a string with the format described here.
-     *
-     * @exception RemoteException if there is a communication
-     * exception during the remote method call.
-     */
-    public String getVersion() throws RemoteException;
-
-    /**
-     * <p>Makes a new connection through this RMI connector.  Each
-     * remote client calls this method to obtain a new RMI object
-     * representing its connection.</p>
-     *
-     * @param credentials this object specifies the user-defined credentials
-     * to be passed in to the server in order to authenticate the user before
-     * creating the <code>RMIConnection</code>.  Can be null.
-     *
-     * @return the newly-created connection object.
-     *
-     * @exception IOException if the new client object cannot be
-     * created or exported, or if there is a communication exception
-     * during the remote method call.
-     *
-     * @exception SecurityException if the given credentials do not
-     * allow the server to authenticate the caller successfully.
-     */
-    public RMIConnection newClient(Object credentials) throws IOException;
-}
--- a/jdk/src/java.management/share/classes/javax/management/remote/rmi/RMIServerImpl.java	Thu Feb 02 12:28:23 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,550 +0,0 @@
-/*
- * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package javax.management.remote.rmi;
-
-import com.sun.jmx.remote.internal.ArrayNotificationBuffer;
-import com.sun.jmx.remote.internal.NotificationBuffer;
-import com.sun.jmx.remote.security.JMXPluggableAuthenticator;
-import com.sun.jmx.remote.util.ClassLogger;
-
-import java.io.Closeable;
-import java.io.IOException;
-import java.lang.ref.WeakReference;
-import java.rmi.Remote;
-import java.rmi.server.RemoteServer;
-import java.rmi.server.ServerNotActiveException;
-import java.security.Principal;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import javax.management.MBeanServer;
-import javax.management.remote.JMXAuthenticator;
-import javax.management.remote.JMXConnectorServer;
-import javax.security.auth.Subject;
-
-/**
- * <p>An RMI object representing a connector server.  Remote clients
- * can make connections using the {@link #newClient(Object)} method.  This
- * method returns an RMI object representing the connection.</p>
- *
- * <p>User code does not usually reference this class directly.
- * RMI connection servers are usually created with the class {@link
- * RMIConnectorServer}.  Remote clients usually create connections
- * either with {@link javax.management.remote.JMXConnectorFactory}
- * or by instantiating {@link RMIConnector}.</p>
- *
- * <p>This is an abstract class.  Concrete subclasses define the
- * details of the client connection objects.</p>
- *
- * @since 1.5
- */
-public abstract class RMIServerImpl implements Closeable, RMIServer {
-    /**
-     * <p>Constructs a new <code>RMIServerImpl</code>.</p>
-     *
-     * @param env the environment containing attributes for the new
-     * <code>RMIServerImpl</code>.  Can be null, which is equivalent
-     * to an empty Map.
-     */
-    public RMIServerImpl(Map<String,?> env) {
-        this.env = (env == null) ? Collections.<String,Object>emptyMap() : env;
-    }
-
-    void setRMIConnectorServer(RMIConnectorServer connServer)
-            throws IOException {
-        this.connServer = connServer;
-    }
-
-    /**
-     * <p>Exports this RMI object.</p>
-     *
-     * @exception IOException if this RMI object cannot be exported.
-     */
-    protected abstract void export() throws IOException;
-
-    /**
-     * Returns a remotable stub for this server object.
-     * @return a remotable stub.
-     * @exception IOException if the stub cannot be obtained - e.g the
-     *            RMIServerImpl has not been exported yet.
-     **/
-    public abstract Remote toStub() throws IOException;
-
-    /**
-     * <p>Sets the default <code>ClassLoader</code> for this connector
-     * server. New client connections will use this classloader.
-     * Existing client connections are unaffected.</p>
-     *
-     * @param cl the new <code>ClassLoader</code> to be used by this
-     * connector server.
-     *
-     * @see #getDefaultClassLoader
-     */
-    public synchronized void setDefaultClassLoader(ClassLoader cl) {
-        this.cl = cl;
-    }
-
-    /**
-     * <p>Gets the default <code>ClassLoader</code> used by this connector
-     * server.</p>
-     *
-     * @return the default <code>ClassLoader</code> used by this
-     * connector server.
-     *
-     * @see #setDefaultClassLoader
-     */
-    public synchronized ClassLoader getDefaultClassLoader() {
-        return cl;
-    }
-
-    /**
-     * <p>Sets the <code>MBeanServer</code> to which this connector
-     * server is attached. New client connections will interact
-     * with this <code>MBeanServer</code>. Existing client connections are
-     * unaffected.</p>
-     *
-     * @param mbs the new <code>MBeanServer</code>.  Can be null, but
-     * new client connections will be refused as long as it is.
-     *
-     * @see #getMBeanServer
-     */
-    public synchronized void setMBeanServer(MBeanServer mbs) {
-        this.mbeanServer = mbs;
-    }
-
-    /**
-     * <p>The <code>MBeanServer</code> to which this connector server
-     * is attached.  This is the last value passed to {@link
-     * #setMBeanServer} on this object, or null if that method has
-     * never been called.</p>
-     *
-     * @return the <code>MBeanServer</code> to which this connector
-     * is attached.
-     *
-     * @see #setMBeanServer
-     */
-    public synchronized MBeanServer getMBeanServer() {
-        return mbeanServer;
-    }
-
-    public String getVersion() {
-        // Expected format is: "protocol-version implementation-name"
-        try {
-            return "1.0 java_runtime_" +
-                    System.getProperty("java.runtime.version");
-        } catch (SecurityException e) {
-            return "1.0 ";
-        }
-    }
-
-    /**
-     * <p>Creates a new client connection.  This method calls {@link
-     * #makeClient makeClient} and adds the returned client connection
-     * object to an internal list.  When this
-     * <code>RMIServerImpl</code> is shut down via its {@link
-     * #close()} method, the {@link RMIConnection#close() close()}
-     * method of each object remaining in the list is called.</p>
-     *
-     * <p>The fact that a client connection object is in this internal
-     * list does not prevent it from being garbage collected.</p>
-     *
-     * @param credentials this object specifies the user-defined
-     * credentials to be passed in to the server in order to
-     * authenticate the caller before creating the
-     * <code>RMIConnection</code>.  Can be null.
-     *
-     * @return the newly-created <code>RMIConnection</code>.  This is
-     * usually the object created by <code>makeClient</code>, though
-     * an implementation may choose to wrap that object in another
-     * object implementing <code>RMIConnection</code>.
-     *
-     * @exception IOException if the new client object cannot be
-     * created or exported.
-     *
-     * @exception SecurityException if the given credentials do not allow
-     * the server to authenticate the user successfully.
-     *
-     * @exception IllegalStateException if {@link #getMBeanServer()}
-     * is null.
-     */
-    public RMIConnection newClient(Object credentials) throws IOException {
-        return doNewClient(credentials);
-    }
-
-    /**
-     * This method could be overridden by subclasses defined in this package
-     * to perform additional operations specific to the underlying transport
-     * before creating the new client connection.
-     */
-    RMIConnection doNewClient(Object credentials) throws IOException {
-        final boolean tracing = logger.traceOn();
-
-        if (tracing) logger.trace("newClient","making new client");
-
-        if (getMBeanServer() == null)
-            throw new IllegalStateException("Not attached to an MBean server");
-
-        Subject subject = null;
-        JMXAuthenticator authenticator =
-            (JMXAuthenticator) env.get(JMXConnectorServer.AUTHENTICATOR);
-        if (authenticator == null) {
-            /*
-             * Create the JAAS-based authenticator only if authentication
-             * has been enabled
-             */
-            if (env.get("jmx.remote.x.password.file") != null ||
-                env.get("jmx.remote.x.login.config") != null) {
-                authenticator = new JMXPluggableAuthenticator(env);
-            }
-        }
-        if (authenticator != null) {
-            if (tracing) logger.trace("newClient","got authenticator: " +
-                               authenticator.getClass().getName());
-            try {
-                subject = authenticator.authenticate(credentials);
-            } catch (SecurityException e) {
-                logger.trace("newClient", "Authentication failed: " + e);
-                throw e;
-            }
-        }
-
-        if (tracing) {
-            if (subject != null)
-                logger.trace("newClient","subject is not null");
-            else logger.trace("newClient","no subject");
-        }
-
-        final String connectionId = makeConnectionId(getProtocol(), subject);
-
-        if (tracing)
-            logger.trace("newClient","making new connection: " + connectionId);
-
-        RMIConnection client = makeClient(connectionId, subject);
-
-        dropDeadReferences();
-        WeakReference<RMIConnection> wr = new WeakReference<RMIConnection>(client);
-        synchronized (clientList) {
-            clientList.add(wr);
-        }
-
-        connServer.connectionOpened(connectionId, "Connection opened", null);
-
-        synchronized (clientList) {
-            if (!clientList.contains(wr)) {
-                // can be removed only by a JMXConnectionNotification listener
-                throw new IOException("The connection is refused.");
-            }
-        }
-
-        if (tracing)
-            logger.trace("newClient","new connection done: " + connectionId );
-
-        return client;
-    }
-
-    /**
-     * <p>Creates a new client connection.  This method is called by
-     * the public method {@link #newClient(Object)}.</p>
-     *
-     * @param connectionId the ID of the new connection.  Every
-     * connection opened by this connector server will have a
-     * different ID.  The behavior is unspecified if this parameter is
-     * null.
-     *
-     * @param subject the authenticated subject.  Can be null.
-     *
-     * @return the newly-created <code>RMIConnection</code>.
-     *
-     * @exception IOException if the new client object cannot be
-     * created or exported.
-     */
-    protected abstract RMIConnection makeClient(String connectionId,
-                                                Subject subject)
-            throws IOException;
-
-    /**
-     * <p>Closes a client connection made by {@link #makeClient makeClient}.
-     *
-     * @param client a connection previously returned by
-     * <code>makeClient</code> on which the <code>closeClient</code>
-     * method has not previously been called.  The behavior is
-     * unspecified if these conditions are violated, including the
-     * case where <code>client</code> is null.
-     *
-     * @exception IOException if the client connection cannot be
-     * closed.
-     */
-    protected abstract void closeClient(RMIConnection client)
-            throws IOException;
-
-    /**
-     * <p>Returns the protocol string for this object.  The string is
-     * <code>rmi</code> for RMI/JRMP.
-     *
-     * @return the protocol string for this object.
-     */
-    protected abstract String getProtocol();
-
-    /**
-     * <p>Method called when a client connection created by {@link
-     * #makeClient makeClient} is closed.  A subclass that defines
-     * <code>makeClient</code> must arrange for this method to be
-     * called when the resultant object's {@link RMIConnection#close()
-     * close} method is called.  This enables it to be removed from
-     * the <code>RMIServerImpl</code>'s list of connections.  It is
-     * not an error for <code>client</code> not to be in that
-     * list.</p>
-     *
-     * <p>After removing <code>client</code> from the list of
-     * connections, this method calls {@link #closeClient
-     * closeClient(client)}.</p>
-     *
-     * @param client the client connection that has been closed.
-     *
-     * @exception IOException if {@link #closeClient} throws this
-     * exception.
-     *
-     * @exception NullPointerException if <code>client</code> is null.
-     */
-    protected void clientClosed(RMIConnection client) throws IOException {
-        final boolean debug = logger.debugOn();
-
-        if (debug) logger.trace("clientClosed","client="+client);
-
-        if (client == null)
-            throw new NullPointerException("Null client");
-
-        synchronized (clientList) {
-            dropDeadReferences();
-            for (Iterator<WeakReference<RMIConnection>> it = clientList.iterator();
-                 it.hasNext(); ) {
-                WeakReference<RMIConnection> wr = it.next();
-                if (wr.get() == client) {
-                    it.remove();
-                    break;
-                }
-            }
-            /* It is not a bug for this loop not to find the client.  In
-               our close() method, we remove a client from the list before
-               calling its close() method.  */
-        }
-
-        if (debug) logger.trace("clientClosed", "closing client.");
-        closeClient(client);
-
-        if (debug) logger.trace("clientClosed", "sending notif");
-        connServer.connectionClosed(client.getConnectionId(),
-                                    "Client connection closed", null);
-
-        if (debug) logger.trace("clientClosed","done");
-    }
-
-    /**
-     * <p>Closes this connection server.  This method first calls the
-     * {@link #closeServer()} method so that no new client connections
-     * will be accepted.  Then, for each remaining {@link
-     * RMIConnection} object returned by {@link #makeClient
-     * makeClient}, its {@link RMIConnection#close() close} method is
-     * called.</p>
-     *
-     * <p>The behavior when this method is called more than once is
-     * unspecified.</p>
-     *
-     * <p>If {@link #closeServer()} throws an
-     * <code>IOException</code>, the individual connections are
-     * nevertheless closed, and then the <code>IOException</code> is
-     * thrown from this method.</p>
-     *
-     * <p>If {@link #closeServer()} returns normally but one or more
-     * of the individual connections throws an
-     * <code>IOException</code>, then, after closing all the
-     * connections, one of those <code>IOException</code>s is thrown
-     * from this method.  If more than one connection throws an
-     * <code>IOException</code>, it is unspecified which one is thrown
-     * from this method.</p>
-     *
-     * @exception IOException if {@link #closeServer()} or one of the
-     * {@link RMIConnection#close()} calls threw
-     * <code>IOException</code>.
-     */
-    public synchronized void close() throws IOException {
-        final boolean tracing = logger.traceOn();
-        final boolean debug   = logger.debugOn();
-
-        if (tracing) logger.trace("close","closing");
-
-        IOException ioException = null;
-        try {
-            if (debug)   logger.debug("close","closing Server");
-            closeServer();
-        } catch (IOException e) {
-            if (tracing) logger.trace("close","Failed to close server: " + e);
-            if (debug)   logger.debug("close",e);
-            ioException = e;
-        }
-
-        if (debug)   logger.debug("close","closing Clients");
-        // Loop to close all clients
-        while (true) {
-            synchronized (clientList) {
-                if (debug) logger.debug("close","droping dead references");
-                dropDeadReferences();
-
-                if (debug) logger.debug("close","client count: "+clientList.size());
-                if (clientList.size() == 0)
-                    break;
-                /* Loop until we find a non-null client.  Because we called
-                   dropDeadReferences(), this will usually be the first
-                   element of the list, but a garbage collection could have
-                   happened in between.  */
-                for (Iterator<WeakReference<RMIConnection>> it = clientList.iterator();
-                     it.hasNext(); ) {
-                    WeakReference<RMIConnection> wr = it.next();
-                    RMIConnection client = wr.get();
-                    it.remove();
-                    if (client != null) {
-                        try {
-                            client.close();
-                        } catch (IOException e) {
-                            if (tracing)
-                                logger.trace("close","Failed to close client: " + e);
-                            if (debug) logger.debug("close",e);
-                            if (ioException == null)
-                                ioException = e;
-                        }
-                        break;
-                    }
-                }
-            }
-        }
-
-        if(notifBuffer != null)
-            notifBuffer.dispose();
-
-        if (ioException != null) {
-            if (tracing) logger.trace("close","close failed.");
-            throw ioException;
-        }
-
-        if (tracing) logger.trace("close","closed.");
-    }
-
-    /**
-     * <p>Called by {@link #close()} to close the connector server.
-     * After returning from this method, the connector server must
-     * not accept any new connections.</p>
-     *
-     * @exception IOException if the attempt to close the connector
-     * server failed.
-     */
-    protected abstract void closeServer() throws IOException;
-
-    private static synchronized String makeConnectionId(String protocol,
-                                                        Subject subject) {
-        connectionIdNumber++;
-
-        String clientHost = "";
-        try {
-            clientHost = RemoteServer.getClientHost();
-            /*
-             * According to the rules specified in the javax.management.remote
-             * package description, a numeric IPv6 address (detected by the
-             * presence of otherwise forbidden ":" character) forming a part
-             * of the connection id must be enclosed in square brackets.
-             */
-            if (clientHost.contains(":")) {
-                clientHost = "[" + clientHost + "]";
-            }
-        } catch (ServerNotActiveException e) {
-            logger.trace("makeConnectionId", "getClientHost", e);
-        }
-
-        final StringBuilder buf = new StringBuilder();
-        buf.append(protocol).append(":");
-        if (clientHost.length() > 0)
-            buf.append("//").append(clientHost);
-        buf.append(" ");
-        if (subject != null) {
-            Set<Principal> principals = subject.getPrincipals();
-            String sep = "";
-            for (Iterator<Principal> it = principals.iterator(); it.hasNext(); ) {
-                Principal p = it.next();
-                String name = p.getName().replace(' ', '_').replace(';', ':');
-                buf.append(sep).append(name);
-                sep = ";";
-            }
-        }
-        buf.append(" ").append(connectionIdNumber);
-        if (logger.traceOn())
-            logger.trace("newConnectionId","connectionId="+buf);
-        return buf.toString();
-    }
-
-    private void dropDeadReferences() {
-        synchronized (clientList) {
-            for (Iterator<WeakReference<RMIConnection>> it = clientList.iterator();
-                 it.hasNext(); ) {
-                WeakReference<RMIConnection> wr = it.next();
-                if (wr.get() == null)
-                    it.remove();
-            }
-        }
-    }
-
-    synchronized NotificationBuffer getNotifBuffer() {
-        //Notification buffer is lazily created when the first client connects
-        if(notifBuffer == null)
-            notifBuffer =
-                ArrayNotificationBuffer.getNotificationBuffer(mbeanServer,
-                                                              env);
-        return notifBuffer;
-    }
-
-    private static final ClassLogger logger =
-        new ClassLogger("javax.management.remote.rmi", "RMIServerImpl");
-
-    /** List of WeakReference values.  Each one references an
-        RMIConnection created by this object, or null if the
-        RMIConnection has been garbage-collected.  */
-    private final List<WeakReference<RMIConnection>> clientList =
-            new ArrayList<WeakReference<RMIConnection>>();
-
-    private ClassLoader cl;
-
-    private MBeanServer mbeanServer;
-
-    private final Map<String, ?> env;
-
-    private RMIConnectorServer connServer;
-
-    private static int connectionIdNumber;
-
-    private NotificationBuffer notifBuffer;
-}
--- a/jdk/src/java.management/share/classes/javax/management/remote/rmi/package.html	Thu Feb 02 12:28:23 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,340 +0,0 @@
-<html>
-<head>
-    <title>RMI connector</title>
-<!--
-Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
-DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-
-This code is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License version 2 only, as
-published by the Free Software Foundation.  Oracle designates this
-particular file as subject to the "Classpath" exception as provided
-by Oracle in the LICENSE file that accompanied this code.
-
-This code is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-version 2 for more details (a copy is included in the LICENSE file that
-accompanied this code).
-
-You should have received a copy of the GNU General Public License version
-2 along with this work; if not, write to the Free Software Foundation,
-Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-
-Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-or visit www.oracle.com if you need additional information or have any
-questions.
--->
-</head>
-<body bgcolor="white">
-    <p>The RMI connector is a connector for the JMX Remote API that
-      uses RMI to transmit client requests to a remote MBean server.
-      This package defines the classes that the user of an RMI
-      connector needs to reference directly, for both the client and
-      server sides.  It also defines certain classes that the user
-      will not usually reference directly, but that must be defined so
-      that different implementations of the RMI connector can
-      interoperate.</p>
-
-    <p>The RMI connector supports the JRMP transport for RMI.</p>
-
-    <p>Like most connectors in the JMX Remote API, an RMI connector
-      usually has an address, which
-      is a {@link javax.management.remote.JMXServiceURL
-      JMXServiceURL}.  The protocol part of this address is
-      <code>rmi</code> for a connector that uses the default RMI
-      transport (JRMP).</p>
-
-    <p>There are two forms for RMI connector addresses:</p>
-
-    <ul>
-      <li>
-	In the <em>JNDI form</em>, the URL indicates <em>where to find
-	an RMI stub for the connector</em>.  This RMI stub is a Java
-	object of type {@link javax.management.remote.rmi.RMIServer
-	RMIServer} that gives remote access to the connector server.
-	With this address form, the RMI stub is obtained from an
-	external directory entry included in the URL.  An external
-	directory is any directory recognized by {@link javax.naming
-	JNDI}, typically the RMI registry, LDAP, or COS Naming.
-
-      <li>
-	In the <em>encoded form</em>, the URL directly includes the
-	information needed to connect to the connector server.  When
-	using RMI/JRMP, the encoded form is the serialized RMI stub
-	for the server object, encoded using BASE64 without embedded
-	newlines.
-    </ul>
-
-    <p>Addresses are covered in more detail below.</p>
-
-
-    <h3>Creating an RMI connector server</h3>
-
-    <p>The usual way to create an RMI connector server is to supply an
-      RMI connector address to the method {@link
-      javax.management.remote.JMXConnectorServerFactory#newJMXConnectorServer
-      JMXConnectorServerFactory.newJMXConnectorServer}.  The MBean
-      server to which the connector server is attached can be
-      specified as a parameter to that method.  Alternatively, the
-      connector server can be registered as an MBean in that MBean
-      server.</p>
-
-    <p>An RMI connector server can also be created by constructing an
-      instance of {@link
-      javax.management.remote.rmi.RMIConnectorServer
-      RMIConnectorServer}, explicitly or through the MBean server's
-      <code>createMBean</code> method.</p>
-
-    <h4>Choosing the RMI transport</h4>
-
-    <p>You can choose the RMI transport by specifying
-      <code>rmi</code> in the <code><em>protocol</em></code> part of the
-      <code>serviceURL</code> when creating the connector server.  You
-      can also create specialized connector servers by instantiating
-      an appropriate subclass of {@link
-      javax.management.remote.rmi.RMIServerImpl RMIServerImpl} and
-      supplying it to the <code>RMIConnectorServer</code>
-      constructor.</p>
-
-
-    <h4><a name="servergen">Connector addresses generated by the
-	server</a></h4>
-
-    <p>If the <code>serviceURL</code> you specify has an empty URL
-      path (after the optional host and port), or if you do not
-      specify a <code>serviceURL</code>, then the connector server
-      will fabricate a new <code>JMXServiceURL</code> that clients can
-      use to connect:</p>
-
-    <ul>
-
-      <li><p>If the <code>serviceURL</code> looks like:</p>
-
-	<pre>
-	<code>service:jmx:rmi://<em>host</em>:<em>port</em></code>
-	</pre>
-
-	<p>then the connector server will generate an {@link
-	javax.management.remote.rmi.RMIJRMPServerImpl
-	RMIJRMPServerImpl} and the returned <code>JMXServiceURL</code>
-	looks like:</p>
-
-	<pre>
-	<code>service:jmx:rmi://<em>host</em>:<em>port</em>/stub/<em>XXXX</em></code>
-	</pre>
-
-	<p>where <code><em>XXXX</em></code> is the serialized form of the
-	stub for the generated object, encoded in BASE64 without
-	newlines.</p>
-
-      <li><p>If there is no <code>serviceURL</code>, there must be a
-	user-provided <code>RMIServerImpl</code>.  The connector server
-        will generate a <code>JMXServiceURL</code> using the <code>rmi</code>
-	form.</p>
-
-    </ul>
-
-    <p>The <code><em>host</em></code> in a user-provided
-      <code>serviceURL</code> is optional.  If present, it is copied
-      into the generated <code>JMXServiceURL</code> but otherwise
-      ignored.  If absent, the generated <code>JXMServiceURL</code>
-      will have the local host name.</p>
-
-    <p>The <code><em>port</em></code> in a user-provided
-      <code>serviceURL</code> is also optional.  If present, it is
-      also copied into the generated <code>JMXServiceURL</code>;
-      otherwise, the generated <code>JMXServiceURL</code> has no port.
-      For an <code>serviceURL</code> using the <code>rmi</code>
-      protocol, the <code><em>port</em></code>, if present, indicates
-      what port the generated remote object should be exported on.  It
-      has no other effect.</p>
-
-    <p>If the user provides an <code>RMIServerImpl</code> rather than a
-      <code>JMXServiceURL</code>, then the generated
-      <code>JMXServiceURL</code> will have the local host name in its
-      <code><em>host</em></code> part and no
-      <code><em>port</em></code>.</p>
-
-
-    <h4><a name="directory">Connector addresses based on directory
-	entries</a></h4>
-
-    <p>As an alternative to the generated addresses just described,
-      the <code>serviceURL</code> address supplied when creating a
-      connector server can specify a <em>directory address</em> in
-      which to store the provided or generated <code>RMIServer</code>
-      stub.  This directory address is then used by both client and
-      server.</p>
-
-    <p>In this case, the <code>serviceURL</code> has the following form:</p>
-
-    <pre>
-    <code>service:jmx:rmi://<em>host</em>:<em>port</em>/jndi/<em>jndi-name</em></code>
-    </pre>
-
-    <p>Here, <code><em>jndi-name</em></code> is a string that can be
-      supplied to {@link javax.naming.InitialContext#bind
-      javax.naming.InitialContext.bind}.</p>
-
-    <p>As usual, the <code><em>host</em></code> and
-      <code>:<em>port</em></code> can be omitted.</p>
-
-    <p>The connector server will generate an
-      <code>RMIServerImpl</code> based on the protocol
-      (<code>rmi</code>) and the <code><em>port</em></code> if any.  When
-      the connector server is started, it will derive a stub from this
-      object using its {@link
-      javax.management.remote.rmi.RMIServerImpl#toStub toStub} method
-      and store the object using the given
-      <code><em>jndi-name</em></code>.  The properties defined by the
-      JNDI API are consulted as usual.</p>
-
-    <p>For example, if the <code>JMXServiceURL</code> is:
-
-      <pre>
-      <code>service:jmx:rmi://ignoredhost/jndi/rmi://myhost/myname</code>
-      </pre>
-
-      then the connector server will generate an
-      <code>RMIJRMPServerImpl</code> and store its stub using the JNDI
-      name
-
-      <pre>
-      <code>rmi://myhost/myname</code>
-      </pre>
-
-      which means entry <code>myname</code> in the RMI registry
-      running on the default port of host <code>myhost</code>.  Note
-      that the RMI registry only allows registration from the local
-      host.  So, in this case, <code>myhost</code> must be the name
-      (or a name) of the host that the connector server is running
-      on.
-
-    <p>In this <code>JMXServiceURL</code>, the first <code>rmi:</code>
-      specifies the RMI
-      connector, while the second <code>rmi:</code> specifies the RMI
-      registry.
-
-    <p>As another example, if the <code>JMXServiceURL</code> is:
-
-      <pre>
-      <code>service:jmx:rmi://ignoredhost/jndi/ldap://dirhost:9999/cn=this,ou=that</code>
-      </pre>
-
-      then the connector server will generate an
-      <code>RMIJRMPServerImpl</code> and store its stub using the JNDI
-      name
-
-      <pre>
-      <code>ldap://dirhost:9999/cn=this,ou=that</code>
-      </pre>
-
-      which means entry <code>cn=this,ou=that</code> in the LDAP
-      directory running on port 9999 of host <code>dirhost</code>.
-
-    <p>If the <code>JMXServiceURL</code> is:
-
-      <pre>
-      <code>service:jmx:rmi://ignoredhost/jndi/cn=this,ou=that</code>
-      </pre>
-
-      then the connector server will generate an
-      <code>RMIJRMPServerImpl</code> and store its stub using the JNDI
-      name
-
-      <pre>
-      <code>cn=this,ou=that</code>
-      </pre>
-
-      For this case to work, the JNDI API must have been configured
-      appropriately to supply the information about what directory to
-      use.
-
-    <p>In these examples, the host name <code>ignoredhost</code> is
-      not used by the connector server or its clients.  It can be
-      omitted, for example:</p>
-
-      <pre>
-      <code>service:jmx:rmi:///jndi/cn=this,ou=that</code>
-      </pre>
-
-    <p>However, it is good practice to use the name of the host
-      where the connector server is running.  This is often different
-      from the name of the directory host.</p>
-
-
-    <h4>Connector server attributes</h4>
-
-    <p>When using the default JRMP transport, RMI socket factories can
-      be specified using the attributes
-      <code>jmx.remote.rmi.client.socket.factory</code> and
-      <code>jmx.remote.rmi.server.socket.factory</code> in the
-      <code>environment</code> given to the
-      <code>RMIConnectorServer</code> constructor.  The values of these
-      attributes must be of type {@link
-      java.rmi.server.RMIClientSocketFactory} and {@link
-      java.rmi.server.RMIServerSocketFactory}, respectively.  These
-      factories are used when creating the RMI objects associated with
-      the connector.</p>
-
-    <h3>Creating an RMI connector client</h3>
-
-    <p>An RMI connector client is usually constructed using {@link
-      javax.management.remote.JMXConnectorFactory}, with a
-      <code>JMXServiceURL</code> that has <code>rmi</code> as its protocol.</p>
-
-    <p>If the <code>JMXServiceURL</code> was generated by the server,
-      as described above under <a href="#servergen">"connector
-      addresses generated by the server"</a>, then the client will
-      need to obtain it directly or indirectly from the server.
-      Typically, the server makes the <code>JMXServiceURL</code>
-      available by storing it in a file or a lookup service.</p>
-
-    <p>If the <code>JMXServiceURL</code> uses the directory syntax, as
-      described above under <a href="#directory">"connector addresses
-      based on directory entries"</a>, then the client may obtain it
-      as just explained, or client and server may both know the
-      appropriate directory entry to use.  For example, if the
-      connector server for the Whatsit agent uses the entry
-      <code>whatsit-agent-connector</code> in the RMI registry on host
-      <code>myhost</code>, then client and server can both know
-      that the appropriate <code>JMXServiceURL</code> is:</p>
-
-    <pre>
-    <code>service:jmx:rmi:///jndi/rmi://myhost/whatsit-agent-connector</code>
-    </pre>
-
-    <p>If you have an RMI stub of type {@link
-      javax.management.remote.rmi.RMIServer RMIServer}, you can
-      construct an RMI connection directly by using the appropriate
-      constructor of {@link javax.management.remote.rmi.RMIConnector
-      RMIConnector}.</p>
-
-    <h3>Dynamic code downloading</h3>
-
-    <p>If an RMI connector client or server receives from its peer an
-      instance of a class that it does not know, and if dynamic code
-      downloading is active for the RMI connection, then the class can
-      be downloaded from a codebase specified by the peer.  The
-      article <a
-    href="{@docRoot}/../technotes/guides/rmi/codebase.html"><em>Dynamic
-    code downloading using Java RMI</em></a> explains this in more
-    detail.</p>
-
-
-    @see <a href="{@docRoot}/../technotes/guides/rmi/index.html">
-	Java&trade; Remote Method
-	Invocation (RMI)</a>
-
-    @see <a href="{@docRoot}/../technotes/guides/jndi/index.html">
-	Java Naming and Directory Interface&trade; (JNDI)</a>
-
-    @see <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045,
-    section 6.8, "Base64 Content-Transfer-Encoding"</a>
-
-
-    @since 1.5
-
-  </body>
-</html>
--- a/jdk/src/java.management/share/classes/module-info.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/src/java.management/share/classes/module-info.java	Thu Feb 02 16:50:46 2017 +0000
@@ -30,8 +30,6 @@
  * JVM and other components in the Java runtime.
  */
 module java.management {
-    requires transitive java.rmi;
-    requires java.naming;
 
     exports java.lang.management;
     exports javax.management;
@@ -41,10 +39,14 @@
     exports javax.management.openmbean;
     exports javax.management.relation;
     exports javax.management.remote;
-    exports javax.management.remote.rmi;
     exports javax.management.timer;
-    exports com.sun.jmx.remote.internal to jdk.management.agent;
-    exports com.sun.jmx.remote.security to jdk.management.agent;
+    exports com.sun.jmx.remote.internal to
+            java.management.rmi,
+            jdk.management.agent;
+    exports com.sun.jmx.remote.security to
+            java.management.rmi,
+            jdk.management.agent;
+    exports com.sun.jmx.remote.util to java.management.rmi;
     exports sun.management to
         jdk.jconsole,
         jdk.management,
--- a/jdk/src/java.rmi/share/classes/module-info.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/src/java.rmi/share/classes/module-info.java	Thu Feb 02 16:50:46 2017 +0000
@@ -41,13 +41,12 @@
     exports sun.rmi.registry to
         jdk.management.agent;
     exports sun.rmi.server to
-        java.management,
+        java.management.rmi,
         jdk.management.agent,
         jdk.jconsole;
     exports sun.rmi.transport to
-        java.management,
+        java.management.rmi,
         jdk.management.agent,
         jdk.jconsole;
     uses java.rmi.server.RMIClassLoaderSpi;
 }
-
--- a/jdk/src/java.se/share/classes/module-info.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/src/java.se/share/classes/module-info.java	Thu Feb 02 16:50:46 2017 +0000
@@ -36,6 +36,7 @@
     requires transitive java.instrument;
     requires transitive java.logging;
     requires transitive java.management;
+    requires transitive java.management.rmi;
     requires transitive java.naming;
     requires transitive java.prefs;
     requires transitive java.rmi;
@@ -47,4 +48,3 @@
     requires transitive java.xml;
     requires transitive java.xml.crypto;
 }
-
--- a/jdk/src/jdk.jconsole/share/classes/module-info.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/src/jdk.jconsole/share/classes/module-info.java	Thu Feb 02 16:50:46 2017 +0000
@@ -26,7 +26,7 @@
 module jdk.jconsole {
     requires transitive java.desktop;
     requires transitive java.management;
-    requires java.logging;
+    requires java.management.rmi;
     requires java.rmi;
     requires jdk.attach;
     requires jdk.jvmstat;
@@ -35,4 +35,3 @@
     exports com.sun.tools.jconsole;
     uses com.sun.tools.jconsole.JConsolePlugin;
 }
-
--- a/jdk/src/jdk.management.agent/share/classes/module-info.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/src/jdk.management.agent/share/classes/module-info.java	Thu Feb 02 16:50:46 2017 +0000
@@ -25,9 +25,9 @@
 
 module jdk.management.agent {
     requires java.management;
+    requires java.management.rmi;
 
     exports jdk.internal.agent to jdk.jconsole;
 
     uses jdk.internal.agent.spi.AgentProvider;
 }
-
--- a/jdk/src/jdk.management.agent/share/classes/sun/management/jmxremote/ConnectorBootstrap.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/src/jdk.management.agent/share/classes/sun/management/jmxremote/ConnectorBootstrap.java	Thu Feb 02 16:50:46 2017 +0000
@@ -73,7 +73,7 @@
 import javax.rmi.ssl.SslRMIServerSocketFactory;
 import javax.security.auth.Subject;
 
-import com.sun.jmx.remote.internal.RMIExporter;
+import com.sun.jmx.remote.internal.rmi.RMIExporter;
 import com.sun.jmx.remote.security.JMXPluggableAuthenticator;
 
 import jdk.internal.agent.Agent;
--- a/jdk/test/javax/management/MBeanInfo/NotificationInfoTest.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/test/javax/management/MBeanInfo/NotificationInfoTest.java	Thu Feb 02 16:50:46 2017 +0000
@@ -27,7 +27,7 @@
  * @summary Test that JMX classes use fully-qualified class names
  * in MBeanNotificationInfo
  * @author Eamonn McManus
- * @modules java.management
+ * @modules java.management.rmi
  * @run clean NotificationInfoTest
  * @run build NotificationInfoTest
  * @run main NotificationInfoTest
--- a/jdk/test/javax/management/MBeanServer/ExceptionTest.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/test/javax/management/MBeanServer/ExceptionTest.java	Thu Feb 02 16:50:46 2017 +0000
@@ -26,7 +26,7 @@
  * @bug 8058865
  * @summary Checks that exceptions are correctly wired (compared to reference).
  * @author Olivier Lagneau
- * @modules java.management
+ * @modules java.management.rmi
  * @run main/othervm/timeout=300 -DDEBUG_STANDARD ExceptionTest
  */
 
@@ -368,5 +368,3 @@
     }
 
 }
-
-
--- a/jdk/test/javax/management/MBeanServer/OldMBeanServerTest.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/test/javax/management/MBeanServer/OldMBeanServerTest.java	Thu Feb 02 16:50:46 2017 +0000
@@ -97,7 +97,7 @@
  * @bug 5072268
  * @summary Test that nothing assumes a post-1.2 MBeanServer
  * @author Eamonn McManus
- * @modules java.management
+ * @modules java.management.rmi
  * @run main/othervm -ea OldMBeanServerTest
  */
 
--- a/jdk/test/javax/management/modelmbean/UnserializableTargetObjectTest.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/test/javax/management/modelmbean/UnserializableTargetObjectTest.java	Thu Feb 02 16:50:46 2017 +0000
@@ -27,7 +27,7 @@
  * @summary Test that a RequiredModelMBean operation can have a targetObject
  * that is not serializable
  * @author Eamonn McManus
- * @modules java.management
+ * @modules java.management.rmi
  * @run clean UnserializableTargetObjectTest
  * @run build UnserializableTargetObjectTest
  * @run main UnserializableTargetObjectTest
--- a/jdk/test/javax/management/mxbean/GenericArrayTypeTest.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/test/javax/management/mxbean/GenericArrayTypeTest.java	Thu Feb 02 16:50:46 2017 +0000
@@ -27,7 +27,7 @@
  * @summary Test support for arrays in parameterized types.
  * @author Luis-Miguel Alventosa
  * @key intermittent
- * @modules java.management
+ * @modules java.management.rmi
  * @run clean GenericArrayTypeTest
  * @run build GenericArrayTypeTest
  * @run main GenericArrayTypeTest
--- a/jdk/test/javax/management/mxbean/MXBeanExceptionHandlingTest.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/test/javax/management/mxbean/MXBeanExceptionHandlingTest.java	Thu Feb 02 16:50:46 2017 +0000
@@ -26,7 +26,7 @@
  * @bug 8058865
  * @summary Checks correct exception and error events from NotificationListener
  * @author Olivier Lagneau
- * @modules java.management
+ * @modules java.management.rmi
  * @library /lib/testlibrary
  * @compile Basic.java
  * @run main/othervm/timeout=300 -DDEBUG_STANDARD MXBeanExceptionHandlingTest -timeForNotificationInSeconds 3
--- a/jdk/test/javax/management/mxbean/MXBeanInteropTest1.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/test/javax/management/mxbean/MXBeanInteropTest1.java	Thu Feb 02 16:50:46 2017 +0000
@@ -26,7 +26,7 @@
  * @bug 8058865
  * @summary Test all MXBeans available by default on the platform
  * @author Olivier Lagneau
- * @modules java.management
+ * @modules java.management.rmi
  * @library /lib/testlibrary
  * @run main/othervm/timeout=300 -DDEBUG_STANDARD MXBeanInteropTest1
  */
--- a/jdk/test/javax/management/mxbean/MXBeanInteropTest2.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/test/javax/management/mxbean/MXBeanInteropTest2.java	Thu Feb 02 16:50:46 2017 +0000
@@ -26,7 +26,7 @@
  * @bug 8058865
  * @summary Checks access to test MXBean
  * @author Olivier Lagneau
- * @modules java.management
+ * @modules java.management.rmi
  * @library /lib/testlibrary
  * @compile Basic.java
  * @run main/othervm/timeout=300 -DDEBUG_STANDARD MXBeanInteropTest2
--- a/jdk/test/javax/management/mxbean/MXBeanNotifTest.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/test/javax/management/mxbean/MXBeanNotifTest.java	Thu Feb 02 16:50:46 2017 +0000
@@ -26,7 +26,7 @@
  * @bug 8058865
  * @summary Checks MXBean proper registration both as its implementation class and interface
  * @author Olivier Lagneau
- * @modules java.management
+ * @modules java.management.rmi
  * @library /lib/testlibrary
  * @compile Basic.java
  * @run main/othervm/timeout=300 -DDEBUG_STANDARD MXBeanNotifTest -numOfNotifications 239 -timeForNotificationInSeconds 4
--- a/jdk/test/javax/management/mxbean/MXBeanTest.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/test/javax/management/mxbean/MXBeanTest.java	Thu Feb 02 16:50:46 2017 +0000
@@ -27,7 +27,7 @@
  * @summary General MXBean test.
  * @author Eamonn McManus
  * @author Jaroslav Bachorik
- * @modules java.management
+ * @modules java.management.rmi
  * @run clean MXBeanTest MerlinMXBean TigerMXBean
  * @run build MXBeanTest MerlinMXBean TigerMXBean
  * @run main MXBeanTest
--- a/jdk/test/javax/management/mxbean/MXBeanWeirdParamTest.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/test/javax/management/mxbean/MXBeanWeirdParamTest.java	Thu Feb 02 16:50:46 2017 +0000
@@ -27,7 +27,7 @@
  * @summary Checks that a serialized instance is not transmitted from an MXBean.
  * All the communication should be done via Open Types
  * @author Olivier Lagneau
- * @modules java.management
+ * @modules java.management.rmi
  * @library /lib/testlibrary
  * @compile Basic.java
  * @run main/othervm/timeout=300 -DDEBUG_STANDARD MXBeanWeirdParamTest
--- a/jdk/test/javax/management/query/SupportedQueryTypesTest.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/test/javax/management/query/SupportedQueryTypesTest.java	Thu Feb 02 16:50:46 2017 +0000
@@ -26,7 +26,7 @@
  * @bug 8058865
  * @summary Tests most of the existing query types.
  * @author Olivier Lagneau
- * @modules java.management
+ * @modules java.management.rmi
  * @compile TestQuery.java
  * @run main/othervm/timeout=300 -DDEBUG_STANDARD SupportedQueryTypesTest -mbeanClassName TestQuery
  */
--- a/jdk/test/javax/management/remote/mandatory/connection/AddressableTest.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/test/javax/management/remote/mandatory/connection/AddressableTest.java	Thu Feb 02 16:50:46 2017 +0000
@@ -26,7 +26,7 @@
  * @bug 6238815
  * @summary test the new interface Addressable
  * @author Shanliang JIANG
- * @modules java.management
+ * @modules java.management.rmi
  * @run clean AddressableTest
  * @run build AddressableTest
  * @run main AddressableTest
--- a/jdk/test/javax/management/remote/mandatory/connection/BrokenConnectionTest.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/test/javax/management/remote/mandatory/connection/BrokenConnectionTest.java	Thu Feb 02 16:50:46 2017 +0000
@@ -27,7 +27,7 @@
  * @summary Tests behaviour when connections break
  * @author Eamonn McManus
  * @key intermittent
- * @modules java.management
+ * @modules java.management.rmi
  * @run clean BrokenConnectionTest
  * @run build BrokenConnectionTest
  * @run main BrokenConnectionTest
--- a/jdk/test/javax/management/remote/mandatory/connection/CloseableTest.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/test/javax/management/remote/mandatory/connection/CloseableTest.java	Thu Feb 02 16:50:46 2017 +0000
@@ -28,7 +28,7 @@
  *          the method "void close() throws IOException;" extend
  *          or implement the java.io.Closeable interface.
  * @author Luis-Miguel Alventosa
- * @modules java.management
+ * @modules java.management.rmi
  * @run clean CloseableTest
  * @run build CloseableTest
  * @run main CloseableTest
--- a/jdk/test/javax/management/remote/mandatory/connection/ConnectionListenerNullTest.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/test/javax/management/remote/mandatory/connection/ConnectionListenerNullTest.java	Thu Feb 02 16:50:46 2017 +0000
@@ -26,7 +26,7 @@
  * @bug 4943248
  * @summary Tests that NullPointerException is thrown when listener is null.
  * @author Daniel Fuchs
- * @modules java.management
+ * @modules java.management.rmi
  * @run clean ConnectionListenerNullTest
  * @run build ConnectionListenerNullTest
  * @run main ConnectionListenerNullTest
--- a/jdk/test/javax/management/remote/mandatory/connection/ConnectionTest.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/test/javax/management/remote/mandatory/connection/ConnectionTest.java	Thu Feb 02 16:50:46 2017 +0000
@@ -26,7 +26,7 @@
  * @bug 4865397
  * @summary Tests remote JMX connections
  * @author Eamonn McManus
- * @modules java.management
+ * @modules java.management.rmi
  * @run clean ConnectionTest
  * @run build ConnectionTest
  * @run main ConnectionTest
--- a/jdk/test/javax/management/remote/mandatory/connection/DaemonRMIExporterTest.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/test/javax/management/remote/mandatory/connection/DaemonRMIExporterTest.java	Thu Feb 02 16:50:46 2017 +0000
@@ -28,7 +28,7 @@
  * @summary test the connector server option that causes it not to prevent the
  * VM from exiting
  * @author Shanliang JIANG, Eamonn McManus
- * @modules java.management
+ * @modules java.management.rmi
  * @run main/othervm DaemonRMIExporterTest
  */
 import java.util.Arrays;
--- a/jdk/test/javax/management/remote/mandatory/connection/GetConnectionTest.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/test/javax/management/remote/mandatory/connection/GetConnectionTest.java	Thu Feb 02 16:50:46 2017 +0000
@@ -26,7 +26,7 @@
  * @bug 4951414
  * @summary Try to get an IOException.
  * @author Shanliang JIANG
- * @modules java.management
+ * @modules java.management.rmi
  * @run clean GetConnectionTest
  * @run build GetConnectionTest
  * @run main GetConnectionTest
--- a/jdk/test/javax/management/remote/mandatory/connection/IIOPURLTest.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/test/javax/management/remote/mandatory/connection/IIOPURLTest.java	Thu Feb 02 16:50:46 2017 +0000
@@ -26,7 +26,7 @@
  * @bug 4886799
  * @summary Check that IIOP URLs have /ior/ in the path
  * @author Eamonn McManus
- * @modules java.management
+ * @modules java.management.rmi
  * @run clean IIOPURLTest
  * @run build IIOPURLTest
  * @run main IIOPURLTest
--- a/jdk/test/javax/management/remote/mandatory/connection/IdleTimeoutTest.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/test/javax/management/remote/mandatory/connection/IdleTimeoutTest.java	Thu Feb 02 16:50:46 2017 +0000
@@ -26,7 +26,8 @@
  * @bug 4886838 4886830 8025204
  * @summary Tests that idle timeouts happen at appropriate times
  * @author Eamonn McManus
- * @modules java.management/com.sun.jmx.remote.util
+ * @modules java.management.rmi
+ *          java.management/com.sun.jmx.remote.util
  * @run clean IdleTimeoutTest
  * @run build IdleTimeoutTest
  * @run main IdleTimeoutTest
--- a/jdk/test/javax/management/remote/mandatory/connection/MultiThreadDeadLockTest.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/test/javax/management/remote/mandatory/connection/MultiThreadDeadLockTest.java	Thu Feb 02 16:50:46 2017 +0000
@@ -45,7 +45,7 @@
  * @bug 6697180
  * @summary test on a client notification deadlock.
  * @author Shanliang JIANG
- * @modules java.management
+ * @modules java.management.rmi
  * @run clean MultiThreadDeadLockTest
  * @run build MultiThreadDeadLockTest
  * @run main MultiThreadDeadLockTest
--- a/jdk/test/javax/management/remote/mandatory/connection/ObjectInputStreamWithLoaderNullCheckTest.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/test/javax/management/remote/mandatory/connection/ObjectInputStreamWithLoaderNullCheckTest.java	Thu Feb 02 16:50:46 2017 +0000
@@ -29,7 +29,7 @@
  *          thrown when constructor is invoked with null class loader as
  *          an argument.
  * @author Amit Sapre
- * @modules java.management/javax.management.remote.rmi:open
+ * @modules java.management.rmi/javax.management.remote.rmi:open
  * @run clean ObjectInputStreamWithLoaderNullCheckTest
  * @run build ObjectInputStreamWithLoaderNullCheckTest
  * @run main ObjectInputStreamWithLoaderNullCheckTest
--- a/jdk/test/javax/management/remote/mandatory/connection/RMIConnectorInternalMapTest.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/test/javax/management/remote/mandatory/connection/RMIConnectorInternalMapTest.java	Thu Feb 02 16:50:46 2017 +0000
@@ -42,7 +42,7 @@
  * @bug 6566891
  * @summary Check no memory leak on RMIConnector's rmbscMap
  * @author Shanliang JIANG
- * @modules java.management/javax.management.remote.rmi:open
+ * @modules java.management.rmi/javax.management.remote.rmi:open
  * @run clean RMIConnectorInternalMapTest
  * @run build RMIConnectorInternalMapTest
  * @run main RMIConnectorInternalMapTest
--- a/jdk/test/javax/management/remote/mandatory/connection/RMIConnectorNullSubjectConnTest.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/test/javax/management/remote/mandatory/connection/RMIConnectorNullSubjectConnTest.java	Thu Feb 02 16:50:46 2017 +0000
@@ -38,7 +38,7 @@
  * @bug 6566891
  * @summary Check no memory leak on RMIConnector's nullSubjectConn
  * @author Shanliang JIANG
- * @modules java.management/javax.management.remote.rmi:open
+ * @modules java.management.rmi/javax.management.remote.rmi:open
  * @run clean RMIConnectorNullSubjectConnTest
  * @run build RMIConnectorNullSubjectConnTest
  * @run main RMIConnectorNullSubjectConnTest
--- a/jdk/test/javax/management/remote/mandatory/connection/RMIConnector_NPETest.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/test/javax/management/remote/mandatory/connection/RMIConnector_NPETest.java	Thu Feb 02 16:50:46 2017 +0000
@@ -26,7 +26,7 @@
  * @summary NPE IN RMIConnector.connect
  * @bug 6984520
  * @library /java/rmi/testlibrary
- * @modules java.management
+ * @modules java.management.rmi
  *          java.rmi/sun.rmi.registry
  *          java.rmi/sun.rmi.server
  *          java.rmi/sun.rmi.transport
@@ -75,4 +75,3 @@
 
     }
 }
-
--- a/jdk/test/javax/management/remote/mandatory/connection/RMIExitTest.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/test/javax/management/remote/mandatory/connection/RMIExitTest.java	Thu Feb 02 16:50:46 2017 +0000
@@ -27,7 +27,7 @@
  * @bug 4917237
  * @summary test that process exit immediately after stop() / close() called
  * @author Jean Francois Denise
- * @modules java.management
+ * @modules java.management.rmi
  * @run clean RMIExitTest
  * @run build RMIExitTest
  * @run main RMIExitTest
--- a/jdk/test/javax/management/remote/mandatory/connection/RMISerializeTest.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/test/javax/management/remote/mandatory/connection/RMISerializeTest.java	Thu Feb 02 16:50:46 2017 +0000
@@ -26,7 +26,7 @@
  * @summary Tests to serialize RMIConnector
  * @bug 5032052
  * @author Shanliang JIANG
- * @modules java.management
+ * @modules java.management.rmi
  * @run clean RMISerializeTest
  * @run build RMISerializeTest
  * @run main RMISerializeTest
--- a/jdk/test/javax/management/remote/mandatory/connectorServer/ConnectorStopDeadlockTest.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/test/javax/management/remote/mandatory/connectorServer/ConnectorStopDeadlockTest.java	Thu Feb 02 16:50:46 2017 +0000
@@ -26,7 +26,7 @@
  * @bug 6475157
  * @summary Tests deadlock in simultaneous connection and connector-server close
  * @author Eamonn McManus
- * @modules java.management
+ * @modules java.management.rmi
  */
 
 /* This test is somewhat dependent on implementation details.  If it suddenly
--- a/jdk/test/javax/management/remote/mandatory/connectorServer/JNDIFailureTest.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/test/javax/management/remote/mandatory/connectorServer/JNDIFailureTest.java	Thu Feb 02 16:50:46 2017 +0000
@@ -27,7 +27,7 @@
  * @summary Tests that JNDI bind failure doesn't leave an orphan RMI
  * Connector Server object
  * @author Eamonn McManus
- * @modules java.management
+ * @modules java.management.rmi
  * @run clean JNDIFailureTest
  * @run build JNDIFailureTest
  * @run main JNDIFailureTest
--- a/jdk/test/javax/management/remote/mandatory/connectorServer/MBSFPreStartPostStartTest.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/test/javax/management/remote/mandatory/connectorServer/MBSFPreStartPostStartTest.java	Thu Feb 02 16:50:46 2017 +0000
@@ -27,7 +27,7 @@
  * @summary Test that setting an MBeanServerForwarder on an already
  *          started RMI connector server has the expected behavior.
  * @author Luis-Miguel Alventosa
- * @modules java.management
+ * @modules java.management.rmi
  * @run clean MBSFPreStartPostStartTest
  * @run build MBSFPreStartPostStartTest
  * @run main MBSFPreStartPostStartTest
--- a/jdk/test/javax/management/remote/mandatory/connectorServer/RMIExporterTest.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/test/javax/management/remote/mandatory/connectorServer/RMIExporterTest.java	Thu Feb 02 16:50:46 2017 +0000
@@ -26,7 +26,7 @@
  * @bug 5016705
  * @summary Tests the use of the RMIExporter class.
  * @author Luis-Miguel Alventosa
- * @modules java.management/com.sun.jmx.remote.internal
+ * @modules java.management.rmi/com.sun.jmx.remote.internal.rmi
  * @run clean RMIExporterTest
  * @run build RMIExporterTest
  * @run main RMIExporterTest
@@ -46,7 +46,7 @@
 import javax.management.remote.JMXConnectorServer;
 import javax.management.remote.JMXConnectorServerFactory;
 import javax.management.remote.JMXServiceURL;
-import com.sun.jmx.remote.internal.RMIExporter;
+import com.sun.jmx.remote.internal.rmi.RMIExporter;
 
 public class RMIExporterTest {
 
--- a/jdk/test/javax/management/remote/mandatory/connectorServer/SetMBeanServerForwarder.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/test/javax/management/remote/mandatory/connectorServer/SetMBeanServerForwarder.java	Thu Feb 02 16:50:46 2017 +0000
@@ -27,7 +27,8 @@
  * @summary Tests that IllegalArgumentException is thrown when
  *          MBeanServerForwrder is null.
  * @author Daniel Fuchs
- * @modules java.management/com.sun.jmx.remote.security
+ * @modules java.management.rmi
+ *          java.management/com.sun.jmx.remote.security
  * @run clean SetMBeanServerForwarder
  * @run build SetMBeanServerForwarder
  * @run main SetMBeanServerForwarder
--- a/jdk/test/javax/management/remote/mandatory/loading/DeserializeEncodedURLTest.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/test/javax/management/remote/mandatory/loading/DeserializeEncodedURLTest.java	Thu Feb 02 16:50:46 2017 +0000
@@ -26,7 +26,7 @@
  * @bug 4924683
  * @summary Check RMI/JRMP stubs can be deserialized using user's loader
  * @author Eamonn McManus
- * @modules java.management
+ * @modules java.management.rmi
  * @run clean DeserializeEncodedURLTest SingleClassLoader
  * @run build DeserializeEncodedURLTest SingleClassLoader
  * @run main DeserializeEncodedURLTest
--- a/jdk/test/javax/management/remote/mandatory/loading/MissingClassTest.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/test/javax/management/remote/mandatory/loading/MissingClassTest.java	Thu Feb 02 16:50:46 2017 +0000
@@ -26,7 +26,7 @@
  * @bug 4915825 4921009 4934965 4977469 8019584
  * @summary Tests behavior when client or server gets object of unknown class
  * @author Eamonn McManus
- * @modules java.management
+ * @modules java.management.rmi
  * @run clean MissingClassTest SingleClassLoader
  * @run build MissingClassTest SingleClassLoader
  * @run main MissingClassTest
--- a/jdk/test/javax/management/remote/mandatory/loading/RMIDownloadTest.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/test/javax/management/remote/mandatory/loading/RMIDownloadTest.java	Thu Feb 02 16:50:46 2017 +0000
@@ -26,7 +26,7 @@
  * @bug 5021246
  * @summary Check that class downloading is supported by RMI connector
  * @author Eamonn McManus
- * @modules java.management
+ * @modules java.management.rmi
  * @run main RMIDownloadTest receive without
  * @run main RMIDownloadTest send without
  * @run main RMIDownloadTest receive with
--- a/jdk/test/javax/management/remote/mandatory/loading/TargetMBeanTest.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/test/javax/management/remote/mandatory/loading/TargetMBeanTest.java	Thu Feb 02 16:50:46 2017 +0000
@@ -26,7 +26,7 @@
  * @bug 4910428
  * @summary Tests target MBean class loader used before JSR 160 loader
  * @author Eamonn McManus
- * @modules java.management
+ * @modules java.management.rmi
  * @run clean TargetMBeanTest
  * @run build TargetMBeanTest
  * @run main TargetMBeanTest
--- a/jdk/test/javax/management/remote/mandatory/notif/ConcurrentModificationTest.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/test/javax/management/remote/mandatory/notif/ConcurrentModificationTest.java	Thu Feb 02 16:50:46 2017 +0000
@@ -26,7 +26,7 @@
  * @bug 7120365
  * @summary test on Concurrent Modification
  * @author Shanliang JIANG
- * @modules java.management
+ * @modules java.management.rmi
  * @run main ConcurrentModificationTest
  */
 
--- a/jdk/test/javax/management/remote/mandatory/notif/DeadListenerTest.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/test/javax/management/remote/mandatory/notif/DeadListenerTest.java	Thu Feb 02 16:50:46 2017 +0000
@@ -25,7 +25,7 @@
  * @test
  * @bug 6957378
  * @summary Test that a listener can be removed remotely from an MBean that no longer exists.
- * @modules java.management/javax.management.remote.rmi:open
+ * @modules java.management.rmi/javax.management.remote.rmi:open
  *          java.management/com.sun.jmx.remote.internal:+open
  * @author Eamonn McManus
  * @run main/othervm -XX:+UsePerfData DeadListenerTest
--- a/jdk/test/javax/management/remote/mandatory/notif/EmptyDomainNotificationTest.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/test/javax/management/remote/mandatory/notif/EmptyDomainNotificationTest.java	Thu Feb 02 16:50:46 2017 +0000
@@ -27,7 +27,7 @@
  * @summary Check that the expected notification is received by the JMX
  *          client even when the domain in the ObjectName is not specified
  * @author Shanliang JIANG
- * @modules java.management
+ * @modules java.management.rmi
  * @run clean EmptyDomainNotificationTest
  * @run build EmptyDomainNotificationTest
  * @run main EmptyDomainNotificationTest
--- a/jdk/test/javax/management/remote/mandatory/notif/ListenerScaleTest.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/test/javax/management/remote/mandatory/notif/ListenerScaleTest.java	Thu Feb 02 16:50:46 2017 +0000
@@ -26,7 +26,7 @@
  * @bug 6338874
  * @summary Check that notification dispatch is not linear in number of MBeans.
  * @author Eamonn McManus
- * @modules java.management
+ * @modules java.management.rmi
  *
  * @library /lib/testlibrary
  * @run build jdk.testlibrary.* ListenerScaleTest
--- a/jdk/test/javax/management/remote/mandatory/notif/NotSerializableNotifTest.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/test/javax/management/remote/mandatory/notif/NotSerializableNotifTest.java	Thu Feb 02 16:50:46 2017 +0000
@@ -26,7 +26,7 @@
  * @summary Tests to send a not serializable notification.
  * @bug 5022196 8132003
  * @author Shanliang JIANG
- * @modules java.management
+ * @modules java.management.rmi
  * @run clean NotSerializableNotifTest
  * @run build NotSerializableNotifTest
  * @run main NotSerializableNotifTest
--- a/jdk/test/javax/management/remote/mandatory/notif/NotifReconnectDeadlockTest.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/test/javax/management/remote/mandatory/notif/NotifReconnectDeadlockTest.java	Thu Feb 02 16:50:46 2017 +0000
@@ -26,7 +26,7 @@
  * @bug 6199899
  * @summary Tests reconnection done by a fetching notif thread.
  * @author Shanliang JIANG
- * @modules java.management
+ * @modules java.management.rmi
  * @run clean NotifReconnectDeadlockTest
  * @run build NotifReconnectDeadlockTest
  * @run main NotifReconnectDeadlockTest
--- a/jdk/test/javax/management/remote/mandatory/notif/NotificationAccessControllerTest.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/test/javax/management/remote/mandatory/notif/NotificationAccessControllerTest.java	Thu Feb 02 16:50:46 2017 +0000
@@ -26,7 +26,8 @@
  * @bug 5106721
  * @summary Check the NotificationAccessController methods are properly called.
  * @author Luis-Miguel Alventosa
- * @modules java.management/com.sun.jmx.remote.security
+ * @modules java.management.rmi
+ *          java.management/com.sun.jmx.remote.security
  * @run clean NotificationAccessControllerTest
  * @run build NotificationAccessControllerTest
  * @run main NotificationAccessControllerTest
--- a/jdk/test/javax/management/remote/mandatory/notif/NotificationBufferCreationTest.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/test/javax/management/remote/mandatory/notif/NotificationBufferCreationTest.java	Thu Feb 02 16:50:46 2017 +0000
@@ -26,7 +26,7 @@
  * @bug 4934236
  * @summary Tests that NotificationBuffer is created when used.
  * @author jfd@...
- * @modules java.management
+ * @modules java.management.rmi
  * @run clean NotificationBufferCreationTest NotificationSender
  * @run build NotificationBufferCreationTest
  * @run main NotificationBufferCreationTest
--- a/jdk/test/javax/management/remote/mandatory/notif/NotificationEmissionTest.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/test/javax/management/remote/mandatory/notif/NotificationEmissionTest.java	Thu Feb 02 16:50:46 2017 +0000
@@ -28,7 +28,7 @@
  * installed. Test the property "jmx.remote.x.check.notification.emission".
  * @author Luis-Miguel Alventosa
  * @key intermittent
- * @modules java.management
+ * @modules java.management.rmi
  * @run clean NotificationEmissionTest
  * @run build NotificationEmissionTest
  * @run main NotificationEmissionTest 1
--- a/jdk/test/javax/management/remote/mandatory/notif/RMINotifTest.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/test/javax/management/remote/mandatory/notif/RMINotifTest.java	Thu Feb 02 16:50:46 2017 +0000
@@ -27,7 +27,7 @@
  * @summary Tests to receive notifications for opened and closed connections
 ions
  * @author sjiang
- * @modules java.management
+ * @modules java.management.rmi
  * @run clean RMINotifTest
  * @run build RMINotifTest
  * @run main RMINotifTest
--- a/jdk/test/javax/management/remote/mandatory/notif/ServerNotifs.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/test/javax/management/remote/mandatory/notif/ServerNotifs.java	Thu Feb 02 16:50:46 2017 +0000
@@ -27,7 +27,7 @@
  * @summary Tests the reception of the notifications for opened and closed
  * connections
  * @author sjiang
- * @modules java.management
+ * @modules java.management.rmi
  * @run clean ServerNotifs
  * @run build ServerNotifs
  * @run main ServerNotifs
--- a/jdk/test/javax/management/remote/mandatory/notif/UnexpectedNotifTest.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/test/javax/management/remote/mandatory/notif/UnexpectedNotifTest.java	Thu Feb 02 16:50:46 2017 +0000
@@ -27,7 +27,7 @@
  * @summary Tests whether a listener receives notifs emitted before the
  * listener is registered.
  * @author Shanliang JIANG
- * @modules java.management
+ * @modules java.management.rmi
  * @run clean UnexpectedNotifTest
  * @run build UnexpectedNotifTest
  * @run main UnexpectedNotifTest
--- a/jdk/test/javax/management/remote/mandatory/passwordAccessFile/NonJMXPrincipalsTest.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/test/javax/management/remote/mandatory/passwordAccessFile/NonJMXPrincipalsTest.java	Thu Feb 02 16:50:46 2017 +0000
@@ -27,7 +27,7 @@
  * @summary Tests that MBeanServerFileAccessController supports
  *          principals other than JMXPrincipal.
  * @author Luis-Miguel Alventosa
- * @modules java.management
+ * @modules java.management.rmi
  * @run clean NonJMXPrincipalsTest SimpleStandard SimpleStandardMBean
  * @run build NonJMXPrincipalsTest SimpleStandard SimpleStandardMBean
  * @run main NonJMXPrincipalsTest
--- a/jdk/test/javax/management/remote/mandatory/passwordAccessFile/PasswordAccessFileTest.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/test/javax/management/remote/mandatory/passwordAccessFile/PasswordAccessFileTest.java	Thu Feb 02 16:50:46 2017 +0000
@@ -27,7 +27,7 @@
  * @summary Tests the use of the "jmx.remote.x.password.file" and
  *          "jmx.remote.x.access.file" environment map properties.
  * @author Luis-Miguel Alventosa
- * @modules java.management
+ * @modules java.management.rmi
  * @run clean PasswordAccessFileTest SimpleStandard SimpleStandardMBean
  * @run build PasswordAccessFileTest SimpleStandard SimpleStandardMBean
  * @run main PasswordAccessFileTest
--- a/jdk/test/javax/management/remote/mandatory/passwordAuthenticator/RMIAltAuthTest.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/test/javax/management/remote/mandatory/passwordAuthenticator/RMIAltAuthTest.java	Thu Feb 02 16:50:46 2017 +0000
@@ -26,7 +26,8 @@
  * @bug 5016508
  * @summary Supplies an alternative JAAS configuration for authenticating RMI clients
  * @author Luis-Miguel Alventosa
- * @modules java.management/com.sun.jmx.remote.security
+ * @modules java.management.rmi
+ *          java.management/com.sun.jmx.remote.security
  * @run clean RMIAltAuthTest
  * @run build RMIAltAuthTest SimpleStandard SimpleStandardMBean
  * @run main RMIAltAuthTest
--- a/jdk/test/javax/management/remote/mandatory/passwordAuthenticator/RMIPasswdAuthTest.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/test/javax/management/remote/mandatory/passwordAuthenticator/RMIPasswdAuthTest.java	Thu Feb 02 16:50:46 2017 +0000
@@ -26,7 +26,8 @@
  * @bug 5016508
  * @summary Tests the default JAAS configuration for authenticating RMI clients
  * @author Luis-Miguel Alventosa
- * @modules java.management/com.sun.jmx.remote.security
+ * @modules java.management.rmi
+ *          java.management/com.sun.jmx.remote.security
  * @run clean RMIPasswdAuthTest
  * @run build RMIPasswdAuthTest SimpleStandard SimpleStandardMBean
  * @run main RMIPasswdAuthTest
--- a/jdk/test/javax/management/remote/mandatory/provider/ProviderTest.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/test/javax/management/remote/mandatory/provider/ProviderTest.java	Thu Feb 02 16:50:46 2017 +0000
@@ -24,7 +24,7 @@
 /*
  * @test ProviderTest.java
  * @summary Tests jar services provider are called
- * @modules java.management
+ * @modules java.management.rmi
  * @run clean ProviderTest provider.JMXConnectorProviderImpl provider.JMXConnectorServerProviderImpl
  * @run build ProviderTest provider.JMXConnectorProviderImpl provider.JMXConnectorServerProviderImpl
  * @run main ProviderTest
--- a/jdk/test/javax/management/remote/mandatory/serverError/JMXServerErrorTest.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/test/javax/management/remote/mandatory/serverError/JMXServerErrorTest.java	Thu Feb 02 16:50:46 2017 +0000
@@ -26,7 +26,8 @@
  * @bug 4871761
  * @summary Tests that JMXServiceErrorException is correctly emitted.
  * @author Daniel Fuchs
- * @modules java.management/com.sun.jmx.remote.security
+ * @modules java.management.rmi
+ *          java.management/com.sun.jmx.remote.security
  * @run clean JMXServerErrorTest
  * @run build JMXServerErrorTest
  * @run main  JMXServerErrorTest
--- a/jdk/test/javax/management/remote/mandatory/socketFactories/RMISocketFactoriesTest.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/test/javax/management/remote/mandatory/socketFactories/RMISocketFactoriesTest.java	Thu Feb 02 16:50:46 2017 +0000
@@ -26,7 +26,7 @@
  * @bug 7654321
  * @summary Tests the use of the custom RMI socket factories.
  * @author Luis-Miguel Alventosa
- * @modules java.management
+ * @modules java.management.rmi
  * @run clean RMISocketFactoriesTest
  * @run build RMISocketFactoriesTest RMIClientFactory RMIServerFactory
  * @run main RMISocketFactoriesTest test_server_factory
--- a/jdk/test/javax/management/remote/mandatory/subjectDelegation/SubjectDelegation1Test.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/test/javax/management/remote/mandatory/subjectDelegation/SubjectDelegation1Test.java	Thu Feb 02 16:50:46 2017 +0000
@@ -27,7 +27,8 @@
  * @summary Tests the use of the subject delegation feature in the
  *          RMI connector
  * @author Luis-Miguel Alventosa
- * @modules java.management/com.sun.jmx.remote.security
+ * @modules java.management.rmi
+ *          java.management/com.sun.jmx.remote.security
  * @run clean SubjectDelegation1Test SimpleStandard SimpleStandardMBean
  * @run build SubjectDelegation1Test SimpleStandard SimpleStandardMBean
  * @run main SubjectDelegation1Test policy11 ok
--- a/jdk/test/javax/management/remote/mandatory/subjectDelegation/SubjectDelegation2Test.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/test/javax/management/remote/mandatory/subjectDelegation/SubjectDelegation2Test.java	Thu Feb 02 16:50:46 2017 +0000
@@ -27,7 +27,8 @@
  * @summary Tests the use of the subject delegation feature on the authenticated
  *          principals within the RMI connector server's creator codebase.
  * @author Luis-Miguel Alventosa
- * @modules java.management/com.sun.jmx.remote.security
+ * @modules java.management.rmi
+ *          java.management/com.sun.jmx.remote.security
  * @run clean SubjectDelegation2Test SimpleStandard SimpleStandardMBean
  * @run build SubjectDelegation2Test SimpleStandard SimpleStandardMBean
  * @run main SubjectDelegation2Test policy21 ok
--- a/jdk/test/javax/management/remote/mandatory/subjectDelegation/SubjectDelegation3Test.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/test/javax/management/remote/mandatory/subjectDelegation/SubjectDelegation3Test.java	Thu Feb 02 16:50:46 2017 +0000
@@ -28,7 +28,8 @@
  *          principals within the RMI connector server's creator codebase with
  *          subject delegation.
  * @author Luis-Miguel Alventosa
- * @modules java.management/com.sun.jmx.remote.security
+ * @modules java.management.rmi
+ *          java.management/com.sun.jmx.remote.security
  * @run clean SubjectDelegation3Test SimpleStandard SimpleStandardMBean
  * @run build SubjectDelegation3Test SimpleStandard SimpleStandardMBean
  * @run main SubjectDelegation3Test policy31 ok
--- a/jdk/test/javax/management/remote/mandatory/util/MapNullValuesTest.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/test/javax/management/remote/mandatory/util/MapNullValuesTest.java	Thu Feb 02 16:50:46 2017 +0000
@@ -31,7 +31,8 @@
  *          Check also that null values for keys are not allowed in
  *          the maps passed to the JMXConnector[Server] factories.
  * @author Luis-Miguel Alventosa
- * @modules java.management/com.sun.jmx.remote.util
+ * @modules java.management.rmi
+ *          java.management/com.sun.jmx.remote.util
  * @run clean MapNullValuesTest
  * @run build MapNullValuesTest
  * @run main MapNullValuesTest
--- a/jdk/test/javax/management/security/AuthorizationTest.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/test/javax/management/security/AuthorizationTest.java	Thu Feb 02 16:50:46 2017 +0000
@@ -26,7 +26,7 @@
  * @bug 8058865
  * @summary Checks various authentication behavior from remote jmx client
  * @author Olivier Lagneau
- * @modules java.management
+ * @modules java.management.rmi
  * @library /lib/testlibrary
  * @compile Simple.java
  * @run main/othervm/timeout=300 -DDEBUG_STANDARD -Dusername=username1 -Dpassword=password1 AuthorizationTest -server -mapType x.access.file;x.password.file -populate -client -mapType credentials
--- a/jdk/test/javax/management/security/SecurityTest.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/test/javax/management/security/SecurityTest.java	Thu Feb 02 16:50:46 2017 +0000
@@ -26,7 +26,7 @@
  * @bug 8058865
  * @summary Checks various secure ways of connecting from remote jmx client
  * @author Olivier Lagneau
- * @modules java.management
+ * @modules java.management.rmi
  * @library /lib/testlibrary
  * @compile MBS_Light.java ServerDelegate.java TestSampleLoginModule.java
  * @run main/othervm/timeout=300 -DDEBUG_STANDARD -Dusername=SQE_username -Dpassword=SQE_password SecurityTest -server -mapType x.password.file -client -mapType credentials
--- a/jdk/test/sun/management/jmxremote/bootstrap/TestManager.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/test/sun/management/jmxremote/bootstrap/TestManager.java	Thu Feb 02 16:50:46 2017 +0000
@@ -57,7 +57,7 @@
         try {
             VirtualMachine.attach(pid).startLocalManagementAgent();
         } catch (Exception x) {
-            throw new IOException(x.getMessage());
+            throw new IOException(x.getMessage(), x);
         }
     }
 
--- a/jdk/test/tools/launcher/modules/listmods/ListModsTest.java	Thu Feb 02 12:28:23 2017 +0100
+++ b/jdk/test/tools/launcher/modules/listmods/ListModsTest.java	Thu Feb 02 16:50:46 2017 +0000
@@ -147,7 +147,7 @@
     @Test
     public void testListWithLimitMods1() throws Exception {
         OutputAnalyzer output
-            = executeTestJava("--limit-modules", "java.management", "--list-modules")
+            = executeTestJava("--limit-modules", "java.management.rmi", "--list-modules")
                 .outputTo(System.out)
                 .errorTo(System.out);
         output.shouldContain("java.rmi");