The RMI implementation
The RMI implementation consists of three abstraction layers.
These abstraction layers are:
- The Stub and Skeleton layer, which intercepts method calls made by the client to the interface reference variable and redirects these calls to a remote RMI service.
- The Remote Reference layer understands how to interpret and manage references made from clients to the remote service objects.
- The bottom layer is the Transport layer, which is based on TCP/IP connections between machines in a network. It provides basic connectivity, as well as some firewall penetration strategies.
On top of the TCP/IP layer, RMI uses a wire-level protocol called Java™ Remote Method Protocol (JRMP), which works like this:
- Objects that require remote behavior should extend the RemoteObject class,
typically through the UnicastRemoteObject subclass.
- The UnicastRemoteObject subclass exports the remote object to make it available for servicing incoming RMI calls.
- Exporting the remote object creates a new server socket, which is bound to a port number.
- A thread is also created that listens for connections on that socket. The server is registered with a registry.
- A client obtains details of connecting to the server from the registry.
- Using the information from the registry, which includes the hostname and the port details of the server's listening socket, the client connects to the server.
- When the client issues a remote method invocation to the server, it creates a TCPConnection object, which opens a socket to the server on the port specified and sends the RMI header information and the marshalled arguments through this connection using the StreamRemoteCall class.
- On the server side:
- When a client connects to the server socket, a new thread is assigned to deal with the incoming call. The original thread can continue listening to the original socket so that additional calls from other clients can be made.
- The server reads the header information and creates a RemoteCall object of its own to deal with unmarshalling the RMI arguments from the socket.
- The serviceCall() method of the Transport class services the incoming call by dispatching it
- The dispatch() method calls the appropriate method on the object and pushes the result back down the wire.
- If the server object throws an exception, the server catches it and marshals it down the wire instead of the return value.
- Back on the client side:
- The return value of the RMI is unmarshalled and returned from the stub back to the client code itself.
- If an exception is thrown from the server, that is unmarshalled and thrown from the stub.