8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package javax.management.remote.rmi;
27
28 import com.sun.jmx.mbeanserver.Util;
29 import com.sun.jmx.remote.internal.ClientCommunicatorAdmin;
30 import com.sun.jmx.remote.internal.ClientListenerInfo;
31 import com.sun.jmx.remote.internal.ClientNotifForwarder;
32 import com.sun.jmx.remote.internal.ProxyRef;
33 import com.sun.jmx.remote.util.ClassLogger;
34 import com.sun.jmx.remote.util.EnvHelp;
35 import java.io.ByteArrayInputStream;
36 import java.io.IOException;
37 import java.io.InputStream;
38 import java.io.InvalidObjectException;
39 import java.io.ObjectInputStream;
40 import java.io.ObjectStreamClass;
41 import java.io.Serializable;
42 import java.lang.ref.WeakReference;
43 import java.lang.reflect.Constructor;
44 import java.lang.reflect.InvocationHandler;
45 import java.lang.reflect.InvocationTargetException;
46 import java.lang.reflect.Module;
47 import java.lang.reflect.Proxy;
48 import java.net.MalformedURLException;
49 import java.rmi.MarshalledObject;
50 import java.rmi.NoSuchObjectException;
51 import java.rmi.Remote;
52 import java.rmi.ServerException;
89 import javax.management.NotificationFilterSupport;
90 import javax.management.NotificationListener;
91 import javax.management.ObjectInstance;
92 import javax.management.ObjectName;
93 import javax.management.QueryExp;
94 import javax.management.ReflectionException;
95 import javax.management.remote.JMXConnectionNotification;
96 import javax.management.remote.JMXConnector;
97 import javax.management.remote.JMXConnectorFactory;
98 import javax.management.remote.JMXServiceURL;
99 import javax.management.remote.NotificationResult;
100 import javax.management.remote.JMXAddressable;
101 import javax.naming.InitialContext;
102 import javax.naming.NamingException;
103 import javax.rmi.ssl.SslRMIClientSocketFactory;
104 import javax.security.auth.Subject;
105 import jdk.internal.module.Modules;
106 import sun.reflect.misc.ReflectUtil;
107 import sun.rmi.server.UnicastRef2;
108 import sun.rmi.transport.LiveRef;
109
110 /**
111 * <p>A connection to a remote RMI connector. Usually, such
112 * connections are made using {@link
113 * javax.management.remote.JMXConnectorFactory JMXConnectorFactory}.
114 * However, specialized applications can use this class directly, for
115 * example with an {@link RMIServer} stub obtained without going
116 * through JNDI.</p>
117 *
118 * @since 1.5
119 */
120 public class RMIConnector implements JMXConnector, Serializable, JMXAddressable {
121
122 private static final ClassLogger logger =
123 new ClassLogger("javax.management.remote.rmi", "RMIConnector");
124
125 private static final long serialVersionUID = 817323035842634473L;
126
127 private RMIConnector(RMIServer rmiServer, JMXServiceURL address,
128 Map<String, ?> environment) {
129 if (rmiServer == null && address == null) throw new
130 IllegalArgumentException("rmiServer and jmxServiceURL both null");
131 initTransients();
132
133 this.rmiServer = rmiServer;
134 this.jmxServiceURL = address;
135 if (environment == null) {
136 this.env = Collections.emptyMap();
137 } else {
138 EnvHelp.checkAttributes(environment);
139 this.env = Collections.unmodifiableMap(environment);
140 }
141 }
142
143 /**
144 * <p>Constructs an {@code RMIConnector} that will connect
145 * the RMI connector server with the given address.</p>
146 *
1373 close(true);
1374 } catch (Exception e) {
1375 // OK.
1376 // We are closing
1377 }
1378 throw ioe; // the connection is closed here.
1379 } else {
1380 // JDK-8049303 possible transient network problem,
1381 // let's try one more time
1382 retried = true;
1383 }
1384 }
1385 }
1386 }
1387 }
1388
1389 private void rethrowDeserializationException(IOException ioe)
1390 throws ClassNotFoundException, IOException {
1391 // specially treating for an UnmarshalException
1392 if (ioe instanceof UnmarshalException) {
1393 throw ioe; // the fix of 6937053 made ClientNotifForwarder.fetchNotifs
1394 // fetch one by one with UnmarshalException
1395 }
1396
1397 // Not serialization problem, return.
1398 }
1399
1400 protected Integer addListenerForMBeanRemovedNotif()
1401 throws IOException, InstanceNotFoundException {
1402 NotificationFilterSupport clientFilter =
1403 new NotificationFilterSupport();
1404 clientFilter.enableType(
1405 MBeanServerNotification.UNREGISTRATION_NOTIFICATION);
1406 MarshalledObject<NotificationFilter> sFilter =
1407 new MarshalledObject<NotificationFilter>(clientFilter);
1408
1409 Integer[] listenerIDs;
1410 final ObjectName[] names =
1411 new ObjectName[] {MBeanServerDelegate.DELEGATE_NAME};
1412 final MarshalledObject<NotificationFilter>[] filters =
1413 Util.cast(new MarshalledObject<?>[] {sFilter});
1918 MBeanServerConnection.getAttribute (or whatever)
1919 -> RMIConnectionImpl_Stub.getAttribute
1920 -> ProxyRef.invoke(...getAttribute...)
1921 -> UnicastRef.invoke(...getAttribute...)
1922 -> internal RMI stuff
1923
1924 Here UnicastRef is the RemoteRef created when the stub was
1925 deserialized (which is of some RMI internal class). It and the
1926 "internal RMI stuff" are loaded by the bootstrap loader, so are
1927 transparent to the stack search. The first non-bootstrap
1928 loader found is our ProxyRefLoader, as required.
1929
1930 In a future version of this code as integrated into J2SE 5,
1931 this workaround could be replaced by direct access to the
1932 internals of RMI. For now, we use the same code base for J2SE
1933 and for the standalone Reference Implementation.
1934
1935 The byte code below encodes the following class, compiled using
1936 J2SE 1.4.2 with the -g:none option.
1937
1938 package com.sun.jmx.remote.internal;
1939
1940 import java.lang.reflect.Method;
1941 import java.rmi.Remote;
1942 import java.rmi.server.RemoteRef;
1943 import com.sun.jmx.remote.internal.ProxyRef;
1944
1945 public class PRef extends ProxyRef {
1946 public PRef(RemoteRef ref) {
1947 super(ref);
1948 }
1949
1950 public Object invoke(Remote obj, Method method,
1951 Object[] params, long opnum)
1952 throws Exception {
1953 return ref.invoke(obj, method, params, opnum);
1954 }
1955 }
1956 */
1957
1958 private static final String rmiServerImplStubClassName =
1959 RMIServer.class.getName() + "Impl_Stub";
1960 private static final Class<?> rmiServerImplStubClass;
1961 private static final String rmiConnectionImplStubClassName =
1962 RMIConnection.class.getName() + "Impl_Stub";
1963 private static final Class<?> rmiConnectionImplStubClass;
1964 private static final String pRefClassName =
1965 "jdk.jmx.remote.internal.PRef";
1966 private static final Constructor<?> proxyRefConstructor;
1967 static {
1968 final String pRefByteCodeString =
1969 "\312\376\272\276\0\0\0\60\0\27\12\0\5\0\15\11\0\4\0\16\13\0\17"+
1970 "\0\20\7\0\21\7\0\22\1\0\6<init>\1\0\36(Ljava/rmi/server/Remote"+
1971 "Ref;)V\1\0\4Code\1\0\6invoke\1\0S(Ljava/rmi/Remote;Ljava/lang/"+
1972 "reflect/Method;[Ljava/lang/Object;J)Ljava/lang/Object;\1\0\12E"+
1973 "xceptions\7\0\23\14\0\6\0\7\14\0\24\0\25\7\0\26\14\0\11\0\12\1"+
1974 "\0\34jdk/jmx/remote/internal/PRef\1\0$com/sun/jmx/remote/inter"+
1975 "nal/ProxyRef\1\0\23java/lang/Exception\1\0\3ref\1\0\33Ljava/rm"+
1976 "i/server/RemoteRef;\1\0\31java/rmi/server/RemoteRef\0!\0\4\0\5"+
1977 "\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"+
1978 "\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"+
1979 "\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"+
1980 "\14\0\0";
1981 final byte[] pRefByteCode =
1982 NoCallStackClassLoader.stringToBytes(pRefByteCodeString);
1983 PrivilegedExceptionAction<Constructor<?>> action =
1984 new PrivilegedExceptionAction<Constructor<?>>() {
1985 public Constructor<?> run() throws Exception {
1986 Class<RMIConnector> thisClass = RMIConnector.class;
1987 ClassLoader thisLoader = thisClass.getClassLoader();
1988 ProtectionDomain thisProtectionDomain =
1989 thisClass.getProtectionDomain();
1990
1991 String proxyRefCName = ProxyRef.class.getName();
1992 ClassLoader cl =
1993 new NoCallStackClassLoader(pRefClassName,
1994 pRefByteCode,
1995 new String[] { proxyRefCName },
1996 thisLoader,
1997 thisProtectionDomain);
1998
1999 Module jmxModule = ProxyRef.class.getModule();
2000 Module rmiModule = RemoteRef.class.getModule();
|
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package javax.management.remote.rmi;
27
28 import com.sun.jmx.remote.internal.ClientCommunicatorAdmin;
29 import com.sun.jmx.remote.internal.ClientListenerInfo;
30 import com.sun.jmx.remote.internal.ClientNotifForwarder;
31 import com.sun.jmx.remote.internal.rmi.ProxyRef;
32 import com.sun.jmx.remote.util.ClassLogger;
33 import com.sun.jmx.remote.util.EnvHelp;
34 import java.io.ByteArrayInputStream;
35 import java.io.IOException;
36 import java.io.InputStream;
37 import java.io.InvalidObjectException;
38 import java.io.ObjectInputStream;
39 import java.io.ObjectStreamClass;
40 import java.io.Serializable;
41 import java.lang.ref.WeakReference;
42 import java.lang.reflect.Constructor;
43 import java.lang.reflect.InvocationHandler;
44 import java.lang.reflect.InvocationTargetException;
45 import java.lang.reflect.Module;
46 import java.lang.reflect.Proxy;
47 import java.net.MalformedURLException;
48 import java.rmi.MarshalledObject;
49 import java.rmi.NoSuchObjectException;
50 import java.rmi.Remote;
51 import java.rmi.ServerException;
88 import javax.management.NotificationFilterSupport;
89 import javax.management.NotificationListener;
90 import javax.management.ObjectInstance;
91 import javax.management.ObjectName;
92 import javax.management.QueryExp;
93 import javax.management.ReflectionException;
94 import javax.management.remote.JMXConnectionNotification;
95 import javax.management.remote.JMXConnector;
96 import javax.management.remote.JMXConnectorFactory;
97 import javax.management.remote.JMXServiceURL;
98 import javax.management.remote.NotificationResult;
99 import javax.management.remote.JMXAddressable;
100 import javax.naming.InitialContext;
101 import javax.naming.NamingException;
102 import javax.rmi.ssl.SslRMIClientSocketFactory;
103 import javax.security.auth.Subject;
104 import jdk.internal.module.Modules;
105 import sun.reflect.misc.ReflectUtil;
106 import sun.rmi.server.UnicastRef2;
107 import sun.rmi.transport.LiveRef;
108 import java.io.NotSerializableException;
109
110 /**
111 * <p>A connection to a remote RMI connector. Usually, such
112 * connections are made using {@link
113 * javax.management.remote.JMXConnectorFactory JMXConnectorFactory}.
114 * However, specialized applications can use this class directly, for
115 * example with an {@link RMIServer} stub obtained without going
116 * through JNDI.</p>
117 *
118 * @since 1.5
119 */
120 public class RMIConnector implements JMXConnector, Serializable, JMXAddressable {
121
122 private static final ClassLogger logger =
123 new ClassLogger("javax.management.remote.rmi", "RMIConnector");
124
125 private static final long serialVersionUID = 817323035842634473L;
126
127 static final class Util {
128 private Util() {}
129
130 /* This method can be used by code that is deliberately violating the
131 * allowed checked casts. Rather than marking the whole method containing
132 * the code with @SuppressWarnings, you can use a call to this method for
133 * the exact place where you need to escape the constraints. Typically
134 * you will "import static" this method and then write either
135 * X x = cast(y);
136 * or, if that doesn't work (e.g. X is a type variable)
137 * Util.<X>cast(y);
138 */
139 @SuppressWarnings("unchecked")
140 public static <T> T cast(Object x) {
141 return (T) x;
142 }
143 }
144
145 private RMIConnector(RMIServer rmiServer, JMXServiceURL address,
146 Map<String, ?> environment) {
147 if (rmiServer == null && address == null) throw new
148 IllegalArgumentException("rmiServer and jmxServiceURL both null");
149 initTransients();
150
151 this.rmiServer = rmiServer;
152 this.jmxServiceURL = address;
153 if (environment == null) {
154 this.env = Collections.emptyMap();
155 } else {
156 EnvHelp.checkAttributes(environment);
157 this.env = Collections.unmodifiableMap(environment);
158 }
159 }
160
161 /**
162 * <p>Constructs an {@code RMIConnector} that will connect
163 * the RMI connector server with the given address.</p>
164 *
1391 close(true);
1392 } catch (Exception e) {
1393 // OK.
1394 // We are closing
1395 }
1396 throw ioe; // the connection is closed here.
1397 } else {
1398 // JDK-8049303 possible transient network problem,
1399 // let's try one more time
1400 retried = true;
1401 }
1402 }
1403 }
1404 }
1405 }
1406
1407 private void rethrowDeserializationException(IOException ioe)
1408 throws ClassNotFoundException, IOException {
1409 // specially treating for an UnmarshalException
1410 if (ioe instanceof UnmarshalException) {
1411 NotSerializableException nse = new NotSerializableException();
1412 nse.initCause(ioe);
1413 throw nse; // the fix of 6937053 made ClientNotifForwarder.fetchNotifs
1414 // fetch one by one with UnmarshalException
1415 }
1416
1417 // Not serialization problem, return.
1418 }
1419
1420 protected Integer addListenerForMBeanRemovedNotif()
1421 throws IOException, InstanceNotFoundException {
1422 NotificationFilterSupport clientFilter =
1423 new NotificationFilterSupport();
1424 clientFilter.enableType(
1425 MBeanServerNotification.UNREGISTRATION_NOTIFICATION);
1426 MarshalledObject<NotificationFilter> sFilter =
1427 new MarshalledObject<NotificationFilter>(clientFilter);
1428
1429 Integer[] listenerIDs;
1430 final ObjectName[] names =
1431 new ObjectName[] {MBeanServerDelegate.DELEGATE_NAME};
1432 final MarshalledObject<NotificationFilter>[] filters =
1433 Util.cast(new MarshalledObject<?>[] {sFilter});
1938 MBeanServerConnection.getAttribute (or whatever)
1939 -> RMIConnectionImpl_Stub.getAttribute
1940 -> ProxyRef.invoke(...getAttribute...)
1941 -> UnicastRef.invoke(...getAttribute...)
1942 -> internal RMI stuff
1943
1944 Here UnicastRef is the RemoteRef created when the stub was
1945 deserialized (which is of some RMI internal class). It and the
1946 "internal RMI stuff" are loaded by the bootstrap loader, so are
1947 transparent to the stack search. The first non-bootstrap
1948 loader found is our ProxyRefLoader, as required.
1949
1950 In a future version of this code as integrated into J2SE 5,
1951 this workaround could be replaced by direct access to the
1952 internals of RMI. For now, we use the same code base for J2SE
1953 and for the standalone Reference Implementation.
1954
1955 The byte code below encodes the following class, compiled using
1956 J2SE 1.4.2 with the -g:none option.
1957
1958 package jdk.jmx.remote.internal.rmi;
1959
1960 import java.lang.reflect.Method;
1961 import java.rmi.Remote;
1962 import java.rmi.server.RemoteRef;
1963 import com.sun.jmx.remote.internal.rmi.ProxyRef;
1964
1965 public class PRef extends ProxyRef {
1966 public PRef(RemoteRef ref) {
1967 super(ref);
1968 }
1969
1970 public Object invoke(Remote obj, Method method,
1971 Object[] params, long opnum)
1972 throws Exception {
1973 return ref.invoke(obj, method, params, opnum);
1974 }
1975 }
1976 */
1977
1978 private static final String rmiServerImplStubClassName =
1979 RMIServer.class.getName() + "Impl_Stub";
1980 private static final Class<?> rmiServerImplStubClass;
1981 private static final String rmiConnectionImplStubClassName =
1982 RMIConnection.class.getName() + "Impl_Stub";
1983 private static final Class<?> rmiConnectionImplStubClass;
1984 private static final String pRefClassName =
1985 "jdk.jmx.remote.internal.rmi.PRef";
1986 private static final Constructor<?> proxyRefConstructor;
1987 static {
1988 final String pRefByteCodeString =
1989 "\312\376\272\276\0\0\0\65\0\27\12\0\5\0\15\11\0\4\0\16\13\0\17"+
1990 "\0\20\7\0\21\7\0\22\1\0\6<init>\1\0\36(Ljava/rmi/server/Remote"+
1991 "Ref;)V\1\0\4Code\1\0\6invoke\1\0S(Ljava/rmi/Remote;Ljava/lang/"+
1992 "reflect/Method;[Ljava/lang/Object;J)Ljava/lang/Object;\1\0\12E"+
1993 "xceptions\7\0\23\14\0\6\0\7\14\0\24\0\25\7\0\26\14\0\11\0\12\1"+
1994 "\0 jdk/jmx/remote/internal/rmi/PRef\1\0(com/sun/jmx/remote/int"+
1995 "ernal/rmi/ProxyRef\1\0\23java/lang/Exception\1\0\3ref\1\0\33Lj"+
1996 "ava/rmi/server/RemoteRef;\1\0\31java/rmi/server/RemoteRef\0!\0"+
1997 "\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"+
1998 "\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"+
1999 "\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"+
2000 "\4\0\1\0\14\0\0";
2001 final byte[] pRefByteCode =
2002 NoCallStackClassLoader.stringToBytes(pRefByteCodeString);
2003 PrivilegedExceptionAction<Constructor<?>> action =
2004 new PrivilegedExceptionAction<Constructor<?>>() {
2005 public Constructor<?> run() throws Exception {
2006 Class<RMIConnector> thisClass = RMIConnector.class;
2007 ClassLoader thisLoader = thisClass.getClassLoader();
2008 ProtectionDomain thisProtectionDomain =
2009 thisClass.getProtectionDomain();
2010
2011 String proxyRefCName = ProxyRef.class.getName();
2012 ClassLoader cl =
2013 new NoCallStackClassLoader(pRefClassName,
2014 pRefByteCode,
2015 new String[] { proxyRefCName },
2016 thisLoader,
2017 thisProtectionDomain);
2018
2019 Module jmxModule = ProxyRef.class.getModule();
2020 Module rmiModule = RemoteRef.class.getModule();
|