Remote method invocation (RMI) is the action of invoking a method of a remote interface on a remote object. Most importantly, a method invocation on a remote object has the same syntax as a method invocation on a local object.
instanceof
operator can be used to test the remote
interfaces supported by a remote object.
Object
are
specialized for remote objects.
java.rmi
and the
java.rmi.server
packages. The following figure shows the relationship
between these interfaces and classes:
java.rmi.remote
. The Remote
interface defines no methods, as shown here:
public interface Remote {}
public interface BankAccount
extends Remote
{
public void deposit (float amount)
throws java.rmi.RemoteException;
public void withdraw (float amount)
throws OverdrawnException, java.rmi.RemoteException;
public float balance()
throws java.rmi.RemoteException;
}
java.rmi.RemoteException
in its throws
clause, in addition to any application-specific exceptions.
java.rmi.RemoteException
class is the superclass of all exceptions
that can be thrown by the RMI runtime. To ensure the robustness of
applications using the RMI system, each method declared in a remote interface
must specify java.rmi.RemoteException
in its throws clause.
java.rmi.RemoteException
is thrown when a remote method invocation
fails (for example when the network fails or the server for the call cannot be
reached). This allows the application making the remote invocation to
determine how best to deal with the remote exception.
java.rmi.server.RemoteObject
and its subclasses, java.rmi.server.RemoteServer
and
java.rmi.server.UnicastRemoteObject
:
java.rmi.server.RemoteObject
class provides the remote
semantics of Object
by implementing methods for hashCode
, equals
,
and toString
.
java.rmi.server.RemoteServer
and concretely by its subclass(es). The
subclass identifies the semantics of the remote reference, for example
whether the server is a single object or is a replicated object requiring
communications with multiple locations.
java.rmi.server.UnicastRemoteObject
class defines a singleton
(unicast) remote object whose references are valid only while the server
process is alive.
java.rmi.server.UnicastRemoteObject
,
thereby inheriting the remote behavior provided by the classes
java.rmi.server.RemoteObject
and
java.rmi.server.RemoteServer
.
BankAcctImpl
class,
which implements the BankAccount
remote interface and which extends the
java.rmi.server.UnicastRemoteObject
class:
package my_package;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
public class BankAccountImpl
extends UnicastRemoteObject
implements BankAccount
{
public void deposit (float amount) throws RemoteException {
...
}
public void withdraw (float amount) throws OverdrawnException,
RemoteException {
...
}
public float balance() throws RemoteException {
...
}
}
java.rmi.server.UnicastRemoteObject
.
However, the implementation class must then assume the responsibility for the
correct remote semantics of the hashCode
, equals
, and toString
methods
inherited from the Object
class.
Because the stub implements the same set of remote interfaces as the remote object's class, the stub has, from the point of view of the Java system, the same type as the remote portions of the server object's type graph. A client, therefore, can make use of the built-in Java operations to check a remote object's type and to cast from one remote interface to another.
Stubs are generated using the rmic compiler.
java.io.Serializable
interface. For more details on how to make classes serializable, see the Java
"Object Serialization Specification." For applets, if the class of an argument or
return value is not available locally, it is loaded dynamically via the
AppletClassLoader. For applications, these classes are loaded by the class
loader that loaded the application; this is either the default class loader (which
uses the local class path) or the RMIClassLoader (which uses the server's
codebase).
Some classes may disallow their being passed (by not being serializable), for example for security reasons. In this case the remote method invocation will fail with an exception.
That is, when a nonremote object appears in a remote method invocation, the content of the nonremote object is copied before invoking the call on the remote object. By default, only the nonstatic and nontransient fields are copied.
Similarly, when a nonremote object is returned from a remote method invocation, a new object is created in the calling virtual machine.
java.rmi.RemoteException
in their
signature, the caller must be prepared to handle those exceptions in addition to
other application specific exceptions. When a java.rmi.RemoteException
is thrown during a remote method invocation, the client may have little or no
information on the outcome of the call - whether a failure happened before,
during, or after the call completed. Therefore, remote interfaces and the calling
methods declared in those interfaces should be designed with these failure
semantics in mind.
Object
class for the equals
, hashCode
,
and toString
methods are not appropriate for remote objects. Therefore, the
java.rmi.server.RemoteObject
class provides implementations for these
methods that have semantics more appropriate for remote objects. In this way,
all objects that need to be available remotely can extend
java.rmi.server.RemoteObject
(typically indirectly via
java.rmi.server.UnicastRemoteObject
).
equals
and hashCode
are overridden by the
java.rmi.server.RemoteObject
class:
java.rmi.server.RemoteObject
class's implementation of the
equals
method determines whether two object references are equal, not
whether the contents of the two objects are equal. This is because
determining equality based on content requires a remote method invocation,
and the signature of equals
does not allow a remote exception to be
thrown.
java.rmi.server.RemoteObject
class's implementation of the
hashCode
method returns the same value for all remote references that
refer to the same underlying remote object (because references to the same
object are considered equal).
toString
method is defined to return a string which represents the
reference of the object. The contents of the string is specific to the reference
type. The current implementation for singleton (unicast) objects includes
information about the object specific to the transport layer (such as host name
and port number) and an object identifier; references to replicated objects
would contain more information.
java.lang.Cloneable
interface. Remote objects do not
implement this interface, but do implement the clone
method so that if
subclasses need to implement Cloneable
the remote classes will function
correctly.
Client stubs are declared final and do not implement clone
. Cloning a stub is
therefore a local operation and cannot be used by clients to create a new
remote object.
RemoteObject
) can use
finalize
to perform their own cleanup as necessary. For example, finalize
can be used to deactivate an object server.
final
by the Object
class and cannot be
overridden:
getClass
notify
notifyAll
wait
getClass
is appropriate for all Java objects,
local or remote; the method needs no special implementation for remote
objects. When used on a remote object, the getClass
method reports the exact
type of the generated stub object. Note that this type reflects only the remote
interfaces implemented by the object, not its local interfaces.
The wait
and notify
methods of Object deal with waiting and notification in
the context of the Java language's threading model. While use of these
methods for remote objects does not break the Java threading model, these
methods do not have the same semantics as they do for local Java objects.
Specifically, using these methods operates on the client's local reference to the
remote object (the stub), not the actual object at the remote site.
java.rmi.Naming
.
For a client to invoke a method on a remote object, that client must first obtain
a reference to the object. A reference to a remote object is usually obtained as a
return value in a method call. The RMI system provides a simple bootstrap
name server from which to obtain remote objects on given hosts. The
java.rmi.Naming
class provides Uniform Resource Locator (URL) based
methods to look up, bind, rebind, unbind, and list the name-object pairings
maintained on a particular host and port.
Here's an example, (without exception handling) of how to bind and look up remote objects:
BankAccount acct = new BankAcctImpl();
String url = "rmi://java.Sun.COM/account";
// bind url to remote object
java.rmi.Naming.bind(url, acct);
...
// lookup account
acct = (BankAccount)java.rmi.Naming.lookup(url);