CONTENTS | PREV | NEXT | Java Remote Method Invocation |
java.net.Socket
and
java.net.ServerSocket
for its connections, instead of
instantiating objects of those classes directly, it calls the
createSocket
and createServerSocket
methods on the current RMISocketFactory
object,
returned by the static method
RMISocketFactory.getSocketFactory
. This allows the
application to have a hook to customize the type of sockets used by
the RMI transport, such as alternate subclasses of the
java.net.Socket
and java.net.ServerSocket
classes. The instance of RMISocketFactory
to be used
can be set once by trusted system code. In JDK1.1, this
customization was limited to relatively global decisions about
socket type, because the only parameters supplied to the factory's
methods were host
and port
(for
createSocket
) and just port
(for
createServerSocket
).
In the Java SE platform,
the new interfaces RMIServerSocketFactory
and
RMIClientSocketFactory
have been introduced to provide
more flexible customization of what protocols are used to
communicate with remote objects.
To allow applications
using RMI to take advantage of these new socket factory interfaces,
several new constructors and exportObject
methods,
that take the client and server socket factory as additional
parameters, have been added to both
UnicastRemoteObject
and
java.rmi.activation.Activatable.
Remote objects exported
with either of the new constructors or exportObject
methods (with RMIClientSocketFactory
and
RMIServerSocketFactory
parameters) will be treated
differently by the RMI runtime. For the lifetime of such a remote
object, the runtime will use the custom
RMIServerSocketFactory
to create a
ServerSocket
to accept incoming calls to the remote
object and use the custom RMIClientSocketFactory
to
create a Socket
to connect clients to the remote
object.
The implementation of
RemoteRef
and ServerRef
used in the stubs
and skeletons for remote objects exported with custom socket
factories is UnicastRef2
and
UnicastServerRef2
, respectively. The wire
representation of the UnicastRef2
type contains a
different representation of the "endpoint" to contact than
the UnicastRef
type has (which used just a host name
string in UTF format, following by an integer port number). For
UnicastRef2
, the endpoint's wire representation
consists of a format byte specifying the contents of the rest of
the endpoint's representation (to allow for future expansion of the
endpoint representation) followed by data in the indicated format.
Currently, the data may consist of a host name in UTF format, a port
number, and optionally (as specified by the endpoint format byte)
the serialized representation of an
RMIClientSocketFactory
object that is used by clients
to generate socket connections to remote object at this endpoint.
The endpoint representation does not contain the
RMIServerSocketFactory
object that was specified when
the remote object was exported.
When calls are made
through references of the UnicastRef2
type, the
runtime uses the createSocket
method of the
RMIClientSocketFactory
object in the endpoint when
creating sockets for connections to the referent remote object.
Also, when the runtime makes DGC "dirty" and
"clean" calls for a particular remote object, it must call
the DGC on the remote JVM using a connection generated from the
same RMIClientSocketFactory
object as specified in the
remote reference, and the DGC implementation on the server side
should verify that this was done correctly.
Remote objects exported
with the older constructor or method on
UnicastRemoteObject
that do not take custom socket
factories as arguments will have RemoteRef
and
ServerRef
of type UnicastRef
and
UnicastServerRef
as before and use the old wire
representation for their endpoints, i.e. a host string in UTF
format followed by an integer specifying the port number. This is
so that RMI servers that do not use new 1.2 features will
interoperate with older RMI clients.
If you export a remote object without specifying a socket factory, or if you export the object with a version of the method UnicastRemoteObject.exportObject
or the constructor UnicastRemoteObject
that does not contain parameters of type RMIClientSocketFactory
and RMIServerSocketFactory
, then the Java runtime uses the system's default RMI socket factory, which opens a socket on a wildcard address, which listens on all interfaces. Consequently, the remote object is exported to all local addresses. To export a remote object to a specific address, do one of the following:
RMISocketFactory.setSocketFactory
.RMIClientSocketFactory
and RMIServerSocketFactory
, and then invoke the method UnicastRemoteObject.exportObject(Remote obj, int port, RMIClientSocketFactory csf, RMIServerSocketFactory ssf)
. Alternatively, subclass the class UnicastRemoteObject
and invoke the constructor UnicastRemoteObject(int port, RMIClientSocketFactory csf, RMIServerSocketFactory ssf)
. This approach is more flexible than invoking the method RMISocketFactory.setSocketFactory
because it enables you to export different objects bound to different interfaces. However, this approach is more complicated. The RMIClientSocketFactory
implementation must be serializable because instances are transmitted to clients by being embedded in the stub. The RMIClientSocketFactory
implementation classes must be made accessible to the client, typically by configuring the client's RMI codebase to point to where the classes are available.localhost
). Note that with this approach, the Java runtime uses the system's default RMI socket factory that opens a socket that listens on all interfaces. The socket still accepts connections from disallowed hosts, domains, and networks, but it immediately closes these connections without processing any RMI requests.RMISocketFactory
Classjava.rmi.server.RMISocketFactory
abstract class
provides an interface for specifying how the transport should
obtain sockets. Note that the class below uses Socket
and ServerSocket
from the java.net
package.
package java.rmi.server; public abstract class RMISocketFactory implements RMIClientSocketFactory, RMIServerSocketFactory { public abstract Socket createSocket(String host, int port) throws IOException; public abstract ServerSocket createServerSocket(int port) throws IOException; public static void setSocketFactory(RMISocketFactory fac) throws IOException {...} public static RMISocketFactory getSocketFactory() {...} public static void setFailureHandler(RMIFailureHandler fh) {...} public static RMIFailureHandler getFailureHandler() {...} }The static method
setSocketFactory
is used to set the socket factory
from which RMI obtains sockets. The application may invoke this
method with its own RMISocketFactory
instance only
once. An application-defined implementation of
RMISocketFactory
could, for example, do preliminary
filtering on the requested connection and throw exceptions, or
return its own extension of the java.net.Socket
or
java.net.ServerSocket
classes, such as ones that
provide a secure communication channel. Note that the
RMISocketFactory
may only be set if the current
security manager allows setting a socket factory; if setting the
socket factory is disallowed, a SecurityException
will
be thrown.
The static method
getSocketFactory
returns the socket factory used by
RMI. The method returns null
if the socket factory is
not set.
The transport layer
invokes the createSocket
and
createServerSocket
methods on the
RMISocketFactory
returned by the
getSocketFactory
method when the transport needs to
create sockets. For example:
RMISocketFactory.getSocketFactory().createSocket(myhost, myport)The method
createSocket
should create a client socket connected
to the specified host and port. The method
createServerSocket
should create a server socket on
the specified port.
The default
transport's implementation of RMISocketFactory
provides for transparent RMI through firewalls using HTTP as
follows:
createSocket
, the factory automatically attempts HTTP
connections to hosts that cannot be contacted with a direct
socket.createServerSocket
, the factory returns a server
socket that automatically detects if a newly accepted connection is
an HTTP POST request. If so, it returns a socket that will
transparently expose only the body of the request to the transport
and format its output as an HTTP response.setFailureHandler
sets the failure handler to be
called by the RMI runtime if the creation of a server socket fails.
The failure handler returns a boolean to indicate if retry should
occur. The default failure handler returns false
,
meaning that by default recreation of sockets is not attempted by
the runtime.
The method
getFailureHandler
returns the current handler for
socket creation failure, or null
if the failure
handler is not set.
RMIServerSocketFactory
InterfaceRMIServerSocketFactory
API documentation.
RMIClientSocketFactory
InterfaceRMIClientSocketFactory
API documentation.