Vous êtes sur la page 1sur 47

Java RMI—Remote Method Invocation

Integrative programming and technologies


Department of Information
Click to add TextTechnology

dbc@csit.fsu.edu 1
Remote Method Invocation
 Java RMI is a mechanism that allows a Java program
running on one computer (e.g., the client) to apply a
method to an object on a different computer (e.g., the
server).
 In itself, the syntax of the remote invocation looks exactly
like an ordinary Java method invocation. The remote
method call can be passed arguments computed in the
context of the local machine. It can return arbitrary values
computed in the context of the remote machine. The RMI
system transparently forwards these arguments and
results.
 RMI is an implementation of the of the Distributed Object
programming model—similar to CORBA, but simpler, and
specialized to the Java language
dbc@csit.fsu.edu 2
Example
 Assume code running in the local machine holds a remote
reference to an object obj on a remote machine:

obj
res = obj.meth(arg) ;
ResType meth(ArgType arg) {
...
return new ResImpl(. . .) ;
}

Local Machine

Remote Machine
dbc@csit.fsu.edu 3
Central Components of Java RMI

 Remote objects—these are normal Java objects, but


their class extends some RMI library class that
incorporates support for remote invocation.
 Remote references—object references that effectively
refer to remote objects, typically on a different computer.
 Remote interfaces—normal Java interfaces, that specify
the “API” of a remote object. They should extend the
marker interface, java.rmi.Remote. The remote
interface must be known to both the local and remote
code.

dbc@csit.fsu.edu 4
Some Supporting Technologies
 Registries—places where the local machine initially
looks to find a reference to a remote object.
 Serialization—reduction of Java objects to a
representation that can be communicated as a byte
stream (for arguments and results).
 Dynamic class loading—needed in various places.
One example is when a remote method returns an object
whose class (e.g. ResImpl) was not previously known on
the calling machine. Also used for stubs—see later.
 Security manager—used to control the behavior of code
loaded from a remote host.

dbc@csit.fsu.edu 5
Related Approaches to Networking
 Sockets
– Traditionally quite hard to program, although the java.net
package makes it relatively easy to establish a socket network
connection to another host. Communication takes place via
streams, but you must define the detailed protocols for message
exchange yourself.
– High-level compared with Unix sockets, but low-level compared
to RMI.
 Remote Procedure Call (RPC)
– An earlier UNIX protocol to allow calling remote procedures.
– Programmers register their application with a host port mapper.
– Protocols for parameter-passing support a limited number of
types.
 CORBA
– See you in the next section
dbc@csit.fsu.edu 6
The Remote Interface
 In RMI, a common remote interface is the minimum
amount of information that must be shared in advance
between “client” and “server” machines. It defines a
high-level “protocol” through which the machines will
communicate.
 A remote interface is an ordinary Java interface, which
must extent the marker interface java.rmi.Remote.
 All methods in a remote interface must be declared to
throw the java.rmi.RemoteException exception.

dbc@csit.fsu.edu 7
A Simple Example
 A file MessageWriter.java contains the interface
definition:
import java.rmi.* ;
public interface MessageWriter extends Remote {
void writeMessage(String s) throws RemoteException
;
}

 This interface defines a single remote method,


writeMessage().

dbc@csit.fsu.edu 8
java.rmi.Remote
 The interface java.rmi.Remote is a marker interface.
 It declares no methods or fields; however, extending it
tells the RMI system to treat the interface concerned as
a remote interface.
 In particular we will see that the rmic compiler
generates extra code for classes that implement remote
interfaces. This code allows their methods to be called
remotely.

dbc@csit.fsu.edu 9
java.rmi.RemoteException
 Requiring all remote methods be declared to throw
RemoteException was a philosophical choice by the
designers of RMI.
 RMI makes remote invocations look syntactically like
local invocation. In practice, though, it cannot defend
from problems unique to distributed computing—
unexpected failure of the network or remote machine.
 Forcing the programmer to handle remote exceptions
helps to encourage thinking about how these partial
failures should be dealt with.
 See the influential essay: “A Note on Distributed
Computing” by Waldo et al, republished in The Jini
Specification:
http://java.sun.com/docs/books/jini

dbc@csit.fsu.edu 10
The Remote Object
 A remote object is an instance of a class that
implements a remote interface.
 Most often this class also extends the library class
java.rmi.server.UnicastRemoteObject. This class
includes a constructor that exports the object to the RMI
system when it is created, thus making the object visible
to the outside world.
 Usually you will not have to deal with this class
explicitly—your remote object classes just have to
extend it.
 One fairly common convention is to name the class of
the remote object after the name of the remote interface
it implements, but append “Impl” to the end.

dbc@csit.fsu.edu 11
A Remote Object Implementation Class
 The file MessageWriterImpl.java contains the class
declaration:
import java.rmi.* ;
import java.rmi.server.* ;
public class MessageWriterImpl extends UnicastRemoteObject
implements MessageWriter {
public MessageWriterImpl() throws RemoteException {
}
public void writeMessage(String s) throws RemoteException {
System.out.println(s) ;
}
}

dbc@csit.fsu.edu 12
Remarks
 The constructor MessageWriterImpl() has an empty
body. But recall that if there is no explicit constructor
invocation in the body of a subclass constructor, it
implicitly invokes super().
 Hence the vital constructor of UnicastRemoteObject is
called.
 This constructor is declared to throw
RemoteException. The MessageWriterImpl()
constructor must be declared to throw this exception in
turn, otherwise there will be a compiler error message.
 Of course the class must also define all the methods of
the remote interface MessageWriter, which it
implements.

dbc@csit.fsu.edu 13
Compiling the Remote Object Class

 To compile classes that implement Remote, you must


use the rmic compiler. The reasons will be discussed
later. For example:
sirah$ rmic MessageWriterImpl

dbc@csit.fsu.edu 14
Client and Server Programs
 We have completed the Java files for the remote object
class itself, but we still need the actual client and server
programs that use this class.
 In general there are some pieces of administrivia one
has to deal with—publishing class files and installing
security managers.
 To minimize distractions, we initially make the
simplifying assumption that both client and server have
copies of all class files for MessageWriter (e.g., they
may share access through shared NFS directories).
 Then we also don’t need a security manager, because
all code is “local”, and therefore trusted.

dbc@csit.fsu.edu 15
A Server Program
 We assume the file HelloServer.java contains the class
declaration:
import java.rmi.* ;
public class HelloServer {
public static void main(String [] args) throws Exception {
MessageWriter server = new MessageWriterImpl() ;
Naming.rebind(“messageservice”, server) ;
}
}

dbc@csit.fsu.edu 16
Remarks
 To avoid cluttering this illustrative code with try-catch
statements, we simply have the main() method throw all
exceptions (not good practice in general).
 This program does two things:
– It creates a remote object with local name server.
– It publishes a remote reference to that object with
external name “MessageWriter”.
 The call to Naming.rebind() places a reference to
server in an RMI registry running on the local host (i.e.,
the host where the HelloServer program is run).
 Client programs can obtain a reference to the remote
object by looking it up in this registry.

dbc@csit.fsu.edu 17
A Client Program
 We assume the file HelloClient.java contains the class
declaration:
import java.rmi.* ;
public class HelloClient {
public static void main(String [] args) throws Exception {
MessageWriter server =
(MessageWriter) Naming.lookup(

“rmi://sirah.csit.fsu.edu/messageservice”) ;
server.writeMessage(“Hello, other world”) ;
}
}

dbc@csit.fsu.edu 18
Remarks
 Again the program does two things:
– It looks up a reference to a remote object with
external name “MessageWriter”, and stores the
returned reference with local name server.
– Finally (!), it invokes the remote method,
writeMessage(), on server.
 The call to Naming.lookup() searches in a remote RMI
registry. Its argument is a URL, with protocol tag “rmi”.
 This example assumes the remote object lives on the
host “sirah”, and has been registered in the default RMI
registry (which happens to listen on port 1099) on that
machine.

dbc@csit.fsu.edu 19
Compiling and Running the Example
 Compile HelloServer and HelloClient on their
respective hosts, e.g.:
sirah$ javac HelloServer
merlot$ javac HelloClient

 Either ensure client and server share the current


directory, or copy all files with names of the form
MessageWriter * .class to the client’s current directory.
 Then. . .

dbc@csit.fsu.edu 20
Running HelloClient/HelloServer

dbc@csit.fsu.edu 21
Running HelloClient/HelloServer

dbc@csit.fsu.edu 22
Running HelloClient/HelloServer

dbc@csit.fsu.edu 23
Running HelloClient/HelloServer

dbc@csit.fsu.edu 24
Running HelloClient/HelloServer

dbc@csit.fsu.edu 25
Remark on Using the RMI Registry

 In this example we ran the RMI registry on its default port.


 In general this is probably a bad idea, especially if the server
is used by many people, because there is no mechanism to
prevent interference.
 It is better to start a registry a non-default port number of your
own choice, e.g.:
sirah$ rmiregistry 4956 &

 The Naming calls become, e.g.:


Naming.rebind(“rmi://sirah.csit.fsu.edu:4956/messageservice”,
server) ;
Naming.lookup(“rmi://sirah.csit.fsu.edu:4956/messageservice”) ;

dbc@csit.fsu.edu 26
Building RMI
 Invocation of a method on a remote object reproduces
the “look and feel” of local invocation amazingly well.
 Yet the internal mechanics of remote invocation are
much more complex than local invocation:
– Arguments—which may be objects of arbitrary complexity—are
somehow collected together into messages suitable for shipping
across the Internet.
– Results (or exceptions) are similarly shipped back.
 Perhaps surprisingly, RMI involves essentially no
fundamental modification to the Java language,
compiler, or virtual machine.
 The illusion of remote invocation is achieved by clever
libraries, plus one relatively simple “post-processor” tool
(rmic).
dbc@csit.fsu.edu 27
Remote References have Interface
Type
 This is a powerful feature, but there is one interesting
restriction:
– If a particular argument or result of a remote method
itself implements Remote, the type appearing in the
method declaration must be a remote interface. The
declared type cannot be a remote implementation
class.
 We have also seen earlier that the remote object
reference returned by Naming.lookup() can be cast to
the expected remote interface type.
– However, this reference cannot be cast it to the
implementation class of the remote object! A
ClassCastException will occur if you try.

dbc@csit.fsu.edu 28
Stubs
 What this tells us is that, however they are obtained—
and however they look—remote references are not, in
reality, Java references to remote objects. They are
Java references to local objects that happen to
implement the same remote interfaces as the remote
objects concerned.
 The local Java object referenced is actually an instance
of a stub class.

dbc@csit.fsu.edu 29
Some Important Parts of RMI
 Stubs.
– Each remote object class has an associated stub class, which
implements the same remote interfaces. An instance of the stub
class is needed on each client. Client-side remote invocations
are “actually” local invocations on the stub class.
 Serialization.
– Arguments and results have to be “marshaled”—converted to a
representation that can be sent over the Net. In general this is a
highly non-trivial transformation for Java objects. Serialization is
also used for distributing stubs.
 The Server-side “Run-time System”.
– This is responsible for listening for invocation requests on
suitable IP ports, and dispatching them to the proper, locally
resident remote object.

dbc@csit.fsu.edu 30
Architecture

Client Internet Server

Call stub method Call remote object


locally Send marshaled method locally
arguments
Client RMI
Remote
Code Stub “Run-time”
Object
System
Send marshaled
Return value result or Return value
or throw exception exception or throw exception

dbc@csit.fsu.edu 31
Example: a File Reading Service
 The earlier “Hello” example involved a very trivial
remote I/O service, whereby a client could write a string
to the console of a server.
 Here we generalize to a more useful service that reads
a file on the server and returns its contents to a client.
 In particular it will illustrate how RMI implicitly uses
serialization for a java.util class, returned as a remote
method result.

dbc@csit.fsu.edu 32
The Remote Interface
 The file FileSource.java:
import java.util.* ;
import java.io.* ;
import java.rmi.* ;
public interface FileSource extends Remote {
public Vector readFile(String File)
throws RemoteException, IOException ;
}

dbc@csit.fsu.edu 33
The Remote Object Implementation
 The definition of FileSourceImpl:
public class FileSourceImpl extends UnicastRemoteObject
implements FileSource {
public FileSourceImpl() throws RemoteException {}
public Vector readFile(String file)
throws RemoteException, IOException {
Vector lines = new Vector() ;
BufferReader in = new BufferReader(new FileReader(file)) ;
while(true) {
String line = in.readLine() ;
if(line == null) break ;
lines.addElement(line) ;
}
return lines ;
}
}
dbc@csit.fsu.edu 34
The Server Program
 The definition of the class FileServer:
public class FileServer {
public static void main(String [] args) throws Exception {
FileSource server = new FileSourceImpl() ;
Naming.rebind(
“rmi://sirah.csit.fsu.edu:4965/fileservice”,
server) ;
}
}

 (We chose the registry port as a random number between


1024 and 64K.)

dbc@csit.fsu.edu 35
The Client Program
 The definition of the class FileClient:
public class FileClient {
public static void main(String [] args) throws Exception {
FileSource server = (FileSource) Naming.lookup(

“rmi://sirah.csit.fsu.edu:4965/fileservice”) ;
Vector lines = server.readFile(“students”) ;
// The remote invocation
for(int i = 0 ; i < lines.size() ; i++)
System.out.println((String) lines.get()) ;
}
}

dbc@csit.fsu.edu 36
Compiling
 On the server:
rmic FileSourceImpl
javac FileServer
– (Note rmic will automatically invoke javac if
FileSourceImpl.java has not previous been compiled. javac, in
turn, will notice a dependency on FileSource.java, and compile
that file if necessary.)
 Copy the files FileSource.class and
FileSourceImpl_Stub.class from server to client.
– Later we will see how to use dynamic class loading to avoid
copying the stub class to the client manually.
 On the client:
javac FileClient

dbc@csit.fsu.edu 37
Running FileClient/FileServer

dbc@csit.fsu.edu 38
Running FileClient/FileServer

dbc@csit.fsu.edu 39
Remarks
 The file students lives on the server. It is not directly
accessible to the client.
 The FileSource object reads the file, and saves its lines
in a Vector.
 The Vector is returned as a result of the remote method
readFile(). Vector, and the String class of the included
elements, both implement Serializable. The return
value is transparently serialized in the server and
deserialized on the client.
 We could also have used an array of String objects—an
array type is serializable if its component type is.

dbc@csit.fsu.edu 40
Example: The RMI Registry
 The RMI registry is a process that normally runs on the
server.
 At first sight the registry seems to have a privileged role
in RMI. Actually it is “just another” remote object.

dbc@csit.fsu.edu 41
The RMI Registry

Client Server

Request
Registry Store
Reference Reference
Client
Code
Remote
Object

dbc@csit.fsu.edu 42
The Registry Remote Interface
 Instead of interacting with the registry indirectly through
the Naming class, it is possible to obtain a direct remote
reference to the registry object.
 Its remote interface is defined in the package
java.rmi.registry. The interface includes:
public interface Registry extends Remote {
public Remote lookup(String name) throws . . . ;
public bind(String name, Remote obj) throws . . . ;
public rebind(String name, Remote obj) throws . . . ;
...
}

dbc@csit.fsu.edu 43
The LocateRegistry Class
 This class constructs a stub for an existing Registry
object. (It can also create a new registry
implementation object, running in the current JVM.)
 The interface includes:
public final class LocateRegistry {
public static Registry getRegistry(String host, int port)
throws . . . {. .
.}
public static Registry createRegistry(int port)
throws . . . {. .
.}
...
}

dbc@csit.fsu.edu 44
Using the Registry Interface Directly
 An alternative definition of the class FileServer:
public class FileServer {
public static void main(String [] args) throws Exception {
FileSource server = new FileSourceImpl() ;
Registry reg =
LocateRegistry.getRegistry(“sirah.csit.fsu.edu”,
4965) ;
reg.rebind(“fileservice”, server) ;
//A remote method invocation
}
}

 We are particularly interested in this example because it


involves passing a remote object implementation, server,
as an argument to a remote method, rebind().
dbc@csit.fsu.edu 45
Passing a Remote Object Argument
 The server argument of rebind() is a true Java reference
to a remote object implementation.
 When the invoke() call is made (on the remote reference
embedded in reg) it uses a customized object-stream
class. As mentioned earlier, this tests for instances of
remote objects among the arguments, and treats them
specially.
 In the output stream, it will replace the implementation
object with a stub obtained by applying the
RemoteObject.toStub() method to server.
 Thus the registry receives a stub.
 This is a general mechanism that applies whenever a
locally resident remote object is passed as an argument to
a remote method.
dbc@csit.fsu.edu 46
Summary
 In principle most of the features that have been
discussed in this section are hidden inside the
implementation of RMI. In an ideal world you would not
have to know about them.
 In practice, to successfully deploy an RMI-based
application, you will probably need to at least be aware
of some fundamental issues.
 You need to be aware of the existence of stub objects,
and the basic working of object serialization.
 You should be aware that references to remote objects
are normally produced by creating a stub object on the
server, then passing this stub to registry and clients in
serialized form.

dbc@csit.fsu.edu 47

Vous aimerez peut-être aussi