J - C D C: AVA Entric Istributed Omputing
J - C D C: AVA Entric Istributed Omputing
The Java language has changed the assumptions governing distributed computing systems.
44 IEEE Micro
ne of the most common ways of communicating between processes in a distributed system is the remote procedure call.1 This communication device allows one process to call a function that runs in some other process, perhaps on a different machine. In the traditional singleprocess programming model, control moves from one point in a program to another point in the same program. With RPC, however, control can ow from a point in one program to a point in another program on another machine. The usual assumptions about RPC systems reect the reality of most distributed environments. We generally assume, for example, that a machine making an RPC can know nothing about the architecture or the instruction set of the machine it is calling. Further, we generally assume (although not always, see the adjacent box) that the programming language used to implement the called program is also unknown. Most distributed systems contain a variety of hardware, operating systems, and serviceseach implemented in the most convenient languageso these assumptions make sense. The Java language and platform2,3 provide a base for distributed computing that changes several of these assumptions. In particular, the Java Virtual Machine allows a group of Java-enabled machines to be treated as a homogeneous group rather than a heterogeneous groupdespite possible differences in the machine architectures and underlying operating systems. Java also makes it possible to safely and dynamically load code in a running Java process. Together, these features allow a system to invoke methods on remote objects, which can move code associated with languagelevel objects from the calling process to the process called and vice versa. Combining these qualities with a language-centric
design not only signicantly simplies traditional RPC systems, it adds functionality that was previously not possible. We designed Java Remote Method Invocation (RMI) to support pure-Java distributed objects in a seamless manner. RMI allows calls to be made between Java objects in different virtual machines, even on different physical machines. RMIs language-centric design allows distributed programming to take place entirely in Java, making available such language features as the Java type system and garbage collection. Coupled with the Java platforms code portability, RMIs language specicity greatly simplies distributed object programming. In addition, the pure-Java approach enables RMI to support distributed polymorphism and pass-by-value objects in remote calls, features which traditional distributed object systems cannot support.
RMIs structure
The RMI system consists of several basic layers; a specific interface and protocol dene the boundary at each layer. Each layer is independent of the next and can be replaced by an alternate implementation without affecting the other layers. For example, the current transport implementation in the Java Development Kit 1.1 is based on TCP (Transmission Control Protocol) using Java sockets. However, a transport based on UDP (User Datagram Protocol) could be used as well. To accomplish transparent transmission of objects from one address space to another, the RMI system uses Java Object Serialization. Another technique, which we call dynamic stub loading, supports client-side stubs that implement the same set of remote interfaces as a remote object itself. Because a stub supporting the exact set of remote types is available to the client of a remote object, that client can use Javas built-in oper-
ators for casting and type checking remote objects. Traditional, language-neutral distributed object systems cannot use built-in operators for casting and type checking, because they do not integrate distributed objects into any languages type system.
Application
Client
Server
RMI
Architectural overview
The RMI systems layers consist of the following: stub/skeletonclient-side stubs (proxies) and serverside skeletons (dispatchers); remote referencereference and invocation behavior (for example, unicast and multicast); transportconnection setup and management, remote object tracking; and distributed garbage collectionreference-counting garbage collection of remote objects. RMI is a layer on top of the Java Virtual Machine, so it leverages the Java systems built-in garbage collection, security, and class-loading mechanisms. The application layer sits on top of the RMI system.
JVM
Figure 1 shows the RMI systems layers. A remote method invocation from a client to a remote server object travels down through the RMI systems layers to the client-side transport layer. Next, the client sends the invocation (potentially via a network communication) to the server-side transport. There, the invocation travels up through the server-side trans-
May/June 1997 45
.
Distributed computing
References
1. M. Kong et al., Network Computing System Reference Manual, Prentice Hall, Englewood Cliffs, N.J., 1987. 2. Common Object Request Broker: Architecture and Specification, OMG Document No. 91.12.1, The Object Management Group, Framingham, Mass.,1991. 3. A.D. Birrell et al., Network Objects, Tech. Report 115, Digital Equipment Corporation Systems Research Center, Palo Alto, Calif. 1994.
port layer to the server. The rest of this section summarizes the functionality at each of RMIs layers. A client invoking a method on a remote server object actually uses a stub (proxy) for the remote object as a conduit to that object. A client-held reference to a remote object, therefore, is a reference to a local stub. This stub is an implementation of the remote objects remote interfaces; it forwards invocation requests to that server object using the remote reference layer. This layer carries out the semantics of the type of invocation. Each remote object implementation chooses its own invocation semantics. For example, the semantics can indicate that communication to the server is unicast (point-topoint), or that the server is part of a multicast group (to accomplish server replication). Thus, the RMI architecture provides a framework for adding new types of remote object communication in the future. The remote reference layer also handles reference semantics for the server. For example, the remote reference layer can handle live and/or persistent references to remote objects. A persistent reference allows objects that are not currently servicing calls to be saved to a permanent store; this
frees resources used by those objects. The next call to such an object reactivates it, returning it to the state it was in prior to being saved to persistent store. The transport layer is responsible for connection setup, connection management, and keeping track of and dispatching to remote objects (the targets of remote calls) in the transports address space. To dispatch to a remote object, the transport forwards the remote call up to the remote reference layer (specic to the server). After performing any necessary server-side behavior, the remote reference layer hands off the request to the server-side skeleton. The skeleton makes an up call to the remote object implementation, which carries out the actual method call. The return value of a call travels back through the skeleton, remote reference layer, and transport on the server side, and then up through the transport, remote reference layer, and stub on the client side. Figure 2 shows the anatomy of an RMI call. In the gure, the remote object (obj) is represented by the client-side stub for the remote object. This stub implements all the remote interfaces (and thus remote methods of those interfaces) that the actual remote implementation object supports.
46
IEEE Micro
A call to method on stub obj result = obj.method(arg1, arg2, ...); marshals the arguments for the call and sends the request to the host Marshal arguments using serialization Stub containing the remote object. The Send request to remote object client-side transport initiates a conTransport {Network communication to remote VM nection to the remote virtual machine and sends a message Skeleton Unmarshal arguments Invoke remote object implementation encoding the RMI call. The server-side transport receives Implementation {return value; the message, looks up the skeleton Receive return/exception for the remote object, and dispatchSkeleton Marshal return/exception es the call to the skeleton. The skeleSend reply ton unmarshals the calls arguments Transport {Network communication back to originating VM and makes the up call to the actual remote object implementation. Stub Unmarshal return value/exception Return value or throw exception When the implementation completes its method by returning a result or throwing an exception, the skeleton marshals the result. Then, the trans- Figure 2. Anatomy of a call. port sends the return result to the originating virtual machine. Finally, the stub initiating the call unmarshals the return result and can be passed through a network to another virtual machine either returns the value or throws the exception. or saved in a le or database for later retrieval. Later or elseWhat is not depicted in Figure 2 is the interaction of the where, object deserialization can construct copies of the origstub with the remote reference layer. The stub interacts inal objects from the stream. directly with the remote reference layer, not with the transObjects are likely to contain references to other objects, port. Any call the stub initiates goes through the reference and the relationships between objects are integral to the layer to ensure appropriate reference semantics. meaning and function of each object. Object serialization traFor example, if a remote reference included connection verses graphs of objects and maintains the relationships so retry behavior, the remote reference would attempt a conthat the graph topology can be recreated. nection retry on behalf of the stub. When the connection The default serialization mechanism makes it simple to was successful, the underlying transport for that reference save and restore objects. All that is needed is for the class to type would take over, marshaling the arguments and senddeclare that it implements the java.lang.Serializable interface. ing the RMI call. This lets the system write or read the object, and does not Another kind of remote reference is one that carries out require the class to implement any special methods to hanmulticast to a set of replicas for a remote object. (RMI does dle serialization. Only when the default behavior is not sufnot yet provide this behavior, but it will in the future.) The cient does the class implement methods to customize the stub for the remote object calls through the remote reference elds and values written to and read from the stream. The layer, which in turn communicates to the replica set via the class assumes control for writing and reading the streams transport. The reference layer provides the abstraction needstate by implementing methods for writes and reads. A typed, so that multiple reference semantics can be carried out ical use of this function would be to write a more compact without a change to the stubs form. A stub simply instructs representation of a sparse data structure. the layer beneath to initiate a call, marshal and unmarshal ObjectOutputStream implements methods for writing parameters, and return results. Various behaviors can take objects to a stream. The writeObject method encodes the place beneath the stub without necessitating a change to the object using information in the virtual machine for the stub itself. objects class and superclasses. Serialization iterates through each class from the highest serializable class down to the objects actual class. For each class, the method writes the Object serialization nontransient and nonstatic public, protected, package, and The RMI system can pass parameters and return values private elds to the stream. For primitive types, it encodes the either by reference or by value. If the object to be passed is values in the stream. In addition, writeObject writes elds itself a remote object, RMI passes a remote reference to that holding references to objects to the stream; these include object. However, if the object is not a remote object, RMI arrays, strings, and classes. If the class has its own methods passes a copy of the object to the receiver, thus giving the implemented for writeObject and readObject, these supereffect of pass-by-value. sede the default mechanism. RMI uses Java Object Serialization to marshal and unmarObjectInputStream implements the complementary shal parameters and return values. Object serialization proreadObject method to read objects from a stream. Reading vides a simple, easy-to-use mechanism for accurately making an object consists of reading its class, allocating a new copies of objects across time and space. It encodes objects instance, and restoring the contents for each of the objects from one virtual machine into a stream of bytes. The stream
May/June 1997 47
.
Distributed computing
Traditional, language-neutral distributed object systems truncate the parameter or return value to the declared type in the remote method signature. With RMI, this is not the case.
object is read from the stream and before the object is returned. These callbacks to the stream allow suitable replacements of one object with another. The substituted objects are always type-checked before assignment, so substitution does not compromise the objects integrity.
classes, from highest serializable class down to the actual class. The default deserialization reads values for primitive types from the stream and assigns them to elds. For object elds, a call to readObject reads the object from the stream. As each object is assigned to a field, object serialization checks that the objects type can be assigned to the eld. Object graphs may be written to the stream; these are reconstructed with the same topology. Each ObjectOutputStream keeps a reference to each object written. The first time an object is written to the stream it is assigned a handle, and the handle remains with the reference to the object. When a new object is written, it is compared with the references for previously written objects. If the object already appears in the stream, it is encoded using the handle. Thus, each object is written to the stream exactly once, so all references to an object within the stream refer to the same instance. This naturally limits the graph traversal and assigns a unique number to each object within the stream. Essential to transporting the object accurately is identifying the objects actual type. The goal is to retain an objects semantics across serialization and deserialization. Classes are identied by name and signature, and the stream includes the classs supertypes as well. When objects are being read from the stream, the normal class-loading mechanisms retrieve the class and verify its signature. This signature is important confirmation that the same class has been found. When methods or elds are added to a class as it evolves, the signature can be declared so that the class-loading mechanisms can identify the class as compatible with previous versions. The mechanisms for object serialization allow subclassing of the output and input streams for class annotation and object substitution. The overridable annotateClass method on the output stream is called for each class written to the stream. A subclass can insert additional information about the class into the stream. A corresponding resolveClass method is called as each class object is read from the stream; it reads the additional information and uses it to find the appropriate class. Before each object is serialized for the first time, the streams replaceObject method gives the stream a chance to examine and act on the object. A corresponding resolveObject method is called on the input stream after an
Downloading code
Remote procedure call systems must generate client-side stub code and link it into a client before making an RPC. This code can be either statically linked to the client or dynamically linked at runtime via libraries available locally or over a network le system. With either static or dynamic linking, the specic code that handles an RPC must be available to the client machine in advance in compiled form. RMI generalizes this technique, using the Java systems dynamic class-loading mechanism at runtime to load (in Javas architecture-neutral bytecode format) the classes that handle method invocations on a remote object. The system downloads the following classes during an RMI call: classes of remote objects and their interfaces; stub and skeleton classes (created by the rmic stub compiler) that serve as proxies for remote objects; and other classes used directly in an RMI-based application, such as parameters to, or return values from, remote method invocations. In addition to class loaders, dynamic class loading employs two other mechanisms: the Java Object Serialization system to transmit class locations over the wire and a security manager to secure the classes loaded. As stated earlier, RMI uses object streams to transmit parameters and return values for remote calls. RMI also places
48
IEEE Micro
additional information in the call public interface StockWatch extends java.rmi.Remote { stream to support dynamic code /** Request notication of stock updates. */ loading. Object serialization allows Stock watch(String stock, StockNotify obj) the RMI runtime to annotate the throws StockNotFoundException, RemoteException; stream with class-specic information when a class descriptor is written. /** Cancel request for stock updates for a particular stock. */ RMI implements ObjectOutputvoid cancel(String stock, StockNotify obj) throws RemoteException; Streams annotateClass method to /** Returns an array of stock update information for the stocks write the code base URL at which the * already registered by the remote object. */ class can be downloaded. Stock[] list(StockNotify obj) throws RemoteException; On the receiving end, RMI uses /** Cancel all requests for stock updates for the remote object. */ ObjectInputStreams resolveClass void cancelAll(StockNotify obj) throws RemoteException; method to read the code base URL } embedded in the stream. If the class is not already defined locally, public interface StockNotify extends java.rmi.Remote { resolveClass then downloads the /** Notication of stock updates for a particular time. */ class from that location. Thus, a void update (Date date, Stock[] stocks) throws RemoteException; classs location (a URL) travels in the } stream along with the objects of that class. A class loaded by RMI is subject to the security restrictions put in place Figure 3. Stock notication service remote interfaces. These interfaces dene by the java.lang.SecurityManager those methods that can be called from another virtual machine. installed for the virtual machine downloading that class. Browsers dene an applet security manager for applets. This security To handle client failure, the client holding a reference to manager prevents applets from accessing files on disk or a remote object leases the reference for a period of time. The opening network connections apart from those to the applets lease period starts when the remote objects runtime receives host of origin; it also institutes other restrictions. For classes the dirty call. It is the client RMI runtimes responsibility to to be downloaded into applets or applications as a result of renew such leases before they expire; it does this by makremote calls, RMI requires a security manager to protect the ing additional dirty calls for the remote references it holds. application and host from potential harm. If the client does not renew a lease before it expires, the distributed garbage collector assumes that the client no longer references that remote object. Garbage collection and leasing In a distributed system, just as in a local system, it is desirable to automatically delete remote objects that are no longer RMI example referenced by any client. Automatic garbage collection frees In this section, well walk through an example of using the programmer from keeping track of remote objects clients RMI to implement a stock notication service. The complete to determine when the program can terminate safely. RMI code for this example is available as part of the Java uses a reference-counting garbage collection algorithm simDevelopers Kit 1.1. The example application consists of two ilar to the one Birrell describes.5 basic remote objects: To accomplish reference-counting garbage collection, the a stock server that accepts requests from clients that wish RMI runtime keeps track of all live remote references withto be notied when specic stocks are updated, and in each Java Virtual Machine. When a live reference enters an applet that participates both as a client of the stock a virtual machine, the runtime increments its reference count. service and as the entity notied when stocks are updatUpon receiving the rst reference to a specic remote object, ed (thus, the applet is also a server). the clients RMI runtime sends a referenced (dirty) message to the remote objects RMI runtime. This way, a remote The applet registers itself with the stock server for price objects runtime keeps track of all clients that hold references updates of various stocks. The stock server keeps track of to objects residing in its virtual machine. the remote objects requiring notication of stock updates, When a given virtual machine discovers a live reference and sends periodic price updates to these remote objects to be unreferenced, the nalization of that reference decre(implemented as applets). The applet displays the stock ments the count. When the client virtual machine has disprices in a graph that it updates dynamically as it receives carded the last reference to a specific remote object, the stock information from the stock server. runtime sends an unreferenced (clean) message to the servTo write an applet or application using RMI, we rst need er. Monotonically increasing sequence numbers maintain to dene the remote interfaces to the remote objects in our ordering among the dirty and clean calls. Interface application. A remote interface is a Java interface that java.rmi.dgc.DGC embodies the server side of RMIs distribdeclares all the methods that may be invoked by clients of uted garbage collector.
May/June 1997 49
.
Distributed computing
/** * Start up the stock server; also creates a registry so * that the StockApplet can lookup the server. */ public static void main(String args[]) { // Create and install the security manager System.setSecurityManager (new RMISecurityManager()); try { LocateRegistry.createRegistry(2005); StockServer server = new StockServer(); Naming.rebind (//:2005/example.stock.StockServer, server); } catch (Exception e) { System.out.println (StockServer.main: an exception occurred: + e.getMessage()); e.printStackTrace(); } } }
Figure 4. The main( ) method to create and install the stock service.
/** Request notication of stock updates. */ public synchronized Stock watch (String stock, StockNotify obj) throws StockNotFoundException { System.out.println(StockServer.watch: + stock ); if (!stockTable.containsKey(stock)) throw new StockNotFoundException(stock); Vector stocks = (Vector)notifyTable.get(obj); // register interested party... if (stocks == null) { stocks = new Vector(); notifyTable.put(obj, stocks); } // add stock to list if (!stocks.contains(stock)) { stocks.addElement(stock); } // start thread to notify watchers... if (notier == null) { notier = new Thread(this, StockNotier); notier.start(); } return (Stock)stockTable.get(stock); }
the remote object. Such clients make calls to remote interfaces, not to the implementation classes of those interfaces. RMI identies remote interfaces as interfaces that extend the abstract interface java.rmi.Remote. The two remote interfaces of interest in the stock service application are StockWatch and StockNotify. The StockWatch interface is the interface to the stock server; the applet implements the StockNotify interface to be notied of stock price updates. (See Figure 3.) Remote objects in the RMI system must implement an interface that extends the java.rmi.Remote interface; both StockWatch and StockNotify do this. Any method in an interface that extends the java.rmi.Remote interface must declare that it may throw an exception of type RemoteException. This RMI-generated exception signals problems with communication between the client and server of the particular call. Next, we implement the stock service as a simple remote object that supports unicast (point-to-point) reference semantics. The stock service directly implements the StockWatch remote interface. The simplest way to implement a server is to extend the java.rmi.server.UnicastRemoteObject class, which provides simple point-to-point reference semantics. During construction, a UnicastRemoteObject makes itself available to the RMI runtime to accept requests from clients that is, the object is exported to the RMI runtime when it is created. The StockServer constructor must include RemoteException in its throws clause, because during construction the object may encounter an error if it cannot be exported to the RMI runtime. public class StockServer extends UnicastRemoteObject implements StockWatch, Runnable { /** Construct the stock server */ public StockServer() throws RemoteException { super(); /* initialize server data structures... */ } This segment shows the constructor for the StockServer; it also shows the beginning of the class denition of a class that will implement the StockWatch interface defined in Figure 3. To create the stock service and make it available to clients, StockServers main method must do several things: create and install a security manager, create a StockServer remote object, and make the StockServer object available to clients via a name facility (see Figure 4). First, the main method creates a security manager to protect itself from code that may be downloaded during the RMI program execution. Some downloaded code cannot be trusted, so a SecurityManager provides a mechanism to sandbox the execution of downloaded code so that it cannot adversely affect the local machine. RMI provides an example security manager, RMISecurityManager, which implements security
50
IEEE Micro
policies similar to those provided by the security manager for applets runpublic class StockApplet extends Applet implements StockNotify ning in a browser.6 { Next, the main method creates the StockServer remote object and /** installs it in a name facility. In this * Initialize applet: export the applet as remote object example, the server creates its own *that gets notied of stock updates. */ registry and uses that as a simple public void init() name facility. RMI provides a name { registry that may be shared by all try { servers running on a host, but any UnicastRemoteObject.exportObject(this); specic server may create and use its URL base = getDocumentBase(); own registry if desired. String serverName = // + base.getHost() + : + The call LocateRegistry.create getParameter(registryPort) + /example.stock.StockServer; Registry(2005) (see Figure 4) creates stockWatch = (StockWatch)Naming.lookup(serverName); a registry on port 2005. The for (int i=0; i<name.length; i++) { StockServer server object is bound in stockWatch.watch(name[i], this); the registry via a call to Naming. stockTable.put(name[i], new StockData(name[i], color[i])); rebind. The rst argument in the } rebind call is the URL (name) for the } catch (Exception e) { remote object. In the specied URL, add(new Label(exception occurred during initialization; + check the log)); add(new Label(e.getClass().getName() + : + e.getMessage())); the host defaults to the local host name, the port is specied as 2005, // fatal error and the name is example.stock. System.out.println(got exception: + e.getMessage()); StockServer. Note that the main e.printStackTrace(); return; method exits after these steps, but the } server process remains alive as long as there are outstanding client refer/* draw graph and labels... */ ences to the StockServer object. We } ensure that the process remains alive by installing a reference to the remote object in the registry. (The system views the registry as a client, and so Figure 6. Implementation of the applet init( ) method for an applet that makes a keeps the server process alive.) remote call to the stock server object dened in Figures 3 through 5. The implementation of the server is not quite nished; we must still implement all its remote methods. Figure 5 shows an implementation of the watch method, which a client uses to request /** Notication of stock updates for a particular time. */ notication of stock price updates. The stock server adds the public void update (Date date, Stock[] stock) { client (the StockNotify object) to its table (notifyTable) of System.out.println(StockApplet.update: + date); remote objects to be notied of updates. A thread that sends // record date periodic notications to clients is started if the thread does not if (time.size() == MAX_UPDATES) { already exist. time.removeElementAt(0); We now turn to the implementation of an applet that acts } time.addElement(date); as a remote object to receive stock updates. StockApplet extends the Applet class and implements the StockNotify // record individual stock updates remote interface so that it can receive stock updates via the int numUpdates = time.size(); update method. Since StockApplet extends the for (int i=0; i<stock.length; i++) { StockData data = java.awt.Applet class, it cannot extend the java.rmi.serv(StockData)stockTable.get(stock[i].symbol); er.UnicastRemoteObject RMI server class to automatically if (data != null) { make the remote object available to accept incoming calls. data.update(stock[i], numUpdates); RMI provides another way to make a remote object avail} able to the RMI runtime so that the object may receive calls } repaint(); from clients (in this case, the client would be StockServer). } By making an explicit call to the static method Unicast RemoteObject.exportObject( ), an application or applet may export a specic remote object to the RMI runtime. Thus, in the applets init method, the applet exports itself as a remote Figure 7. Implementation of the applets remote method object to the RMI runtime. update( ), called by the stock server.
May/June 1997 51
.
Distributed computing
RMI also allows objects to be passed by value. Traditional distributed systems do not allow pass-by-value objects because such objects imply that the code is available for the object on the receiving end.
distributed systems do not allow pass-by-value objects because such objects imply that the code is available for the object on the receiving end. In multilanguage systems, code is not downloaded due to the systems heterogeneous nature. While it is theoretically possible to have a heterogeneous system that downloads compiled code, such a system would require code compilation for all possible platforms, for all possible classes, as well as a static set of classes. We can give a powerful example of exploiting polymorphism in RMI by defining a compute server interface that executes the run method for arbitrary Task objects: public interface Task implements Serializable { Object run(); } public interface ComputeServer extends java.rmi.Remote { Object runTask(Task task) throws java.rmi.RemoteException; } A client could dene any object that implemented the nonremote Task interface and have its run method executed by a remote compute server. More specically, it could send a task object to a ComputeServer in an RMI call; the task could be executed via a call to the tasks run method, and the result could be returned to the caller. For example, public class FFT implements Task { public FFT(args..) { .... } public Object run() { // computes FFT and returns the result } } We could compute a fast Fourier transform (FFT) on a remote server simply by executing the following code: ComputeServer comp = (ComputeServer)Naming.Lookup (//buttery/computer); FFT fft = new FFT(args...); Object obj = comp.runTask(fft); // display result returned in obj... Such applications would be difcult if not impossible in traditional distributed object systems. Since RMI downloads code, this application is not only possible, but an easy extension of the general programming patterns used in the language.
Next, the applet must register with the stock server to receive stock updates. This entails looking up the stock server by name in its registry, and then invoking the stock servers watch method for each stock. The name for the server is composed of the code base host (available via a call to base.getHost()), the registrys port (available via an applet parameter congured for this purpose), and the name of the stock server, example.stock.StockServer. The applet uses the Naming.lookup method to look up the StockWatch remote object by name, then it invokes the watch method for each stock for which it needs updates. See Figure 6. In its role as a remote object, StockApplet implements the StockNotify interface, which consists of a single update method for receiving a stock price update. The implementation of this method simply stores the stock update information and repaints the graph to display the new information. See Figure 7. For this example, we have elided much of the code that deals with the specics of storing and displaying the stock information. For details, see the full code in the RMI documentation in the JDK 1.1 release. This example illustrates how to write a simple peer-topeer distributed application using RMI. It does not fully demonstrate all of RMIs features, but it does show that building an application in RMI is straightforward. One of RMIs strengths is that an object may be passed polymorphically in an RMI call. That is, subtypes of the declared parameter types of a remote method can be passed in a remote method call, and the code for the subtype is downloaded as a side effect of the call. Traditional distributed object systems do not allow parameter polymorphism because they are language-neutral and cannot support downloading code. For example, in the example in Figure 7, the server only cared that it was communicating with an object that implemented the StockNotify interface. However, the stub for the StockApplet that is passed to the StockServer supports the complete set of remote interfaces that the StockApplet supports. The StockServer could have discovered other remote interfaces that the StockNotify object implemented using standard Java language mechanisms (for example, instanceof). RMI also allows objects to be passed by value. Traditional
52
IEEE Micro
support for persistent remote references that are valid from run to run of a serverthat is, such references persist and are valid over time; support for automatic server activation in conjunction with persistent remote references; support for RMI over secure transports such as SSL and/or SKIP; support for multicast remote references; and performance enhancements. Beyond these enhancements to the basic RMI platform, we plan on using RMIs abilities to investigate other topics in the area of distributed systems. Since RMI allows systems to move code as well as data, and since it supports full polymorphic typing, we believe it is a base for investigations into such areas as agent technology and just-in-time software distribution.
Availability
The Java Remote Method Invocation System is part of the basic Java Development Kit release 1.1. Versions of JDK 1.1 for Solaris, Windows95, and WindowsNT can be obtained via the Web at http://www.javasoft.com/.
Wollrath received an MS from the University of Massachusetts, Lowell, and a BS from Merrimack College. She is a member of the IEEE and the ACM. Jim Waldo is a senior staff engineer with JavaSoft, where he is responsible for the overall architecture of pure Java distributed systems. Prior to joining JavaSoft, he was principal investigator for the large-scale distribution project in Sun Microsystems Laboratories. Waldo received a PhD from the University of Massachusetts, Amherst. He also holds masters degrees in philosophy and linguistics and a BA from the University of Utah. He is a member of the IEEE and the ACM. Roger Riggs is a senior staff engineer with JavaSoft, where he is responsible for the object serialization system. Prior to joining JavaSoft, he did research in multimedia and large-scale distributed computing at Sun Microsystems Laboratories. Riggs received a BS from Carnegie Mellon University. He is a member of the ACM.
References
1. A.D. Birrell and B.J. Nelson, Implementing Remote Procedure Calls, ACM Trans. Computer Systems, Vol. 2, 1984, pp. 3959. 2. J. Gosling, B. Joy, and G. Steele, The Java Language Specication, Addison-Wesley Longman, Reading, Mass., 1996. 3. T. Lindholm and F. Yellin, The Java Virtual Machine Specication, Addison-Wesley Longman, Reading, Mass., 1996. 4. G. Booch, Object Oriented Design with Applications, Benjamin/Cummings Publishing Company, Inc., Redwood City, Calif., 1991. 5. A.D. Birrell et al., Network Objects, Technical Report 115, Digital Equipment Corporation Systems Research Center, Palo Alto, Calif., 1994. 6. A. van Hoff, S. Shaio, and O. Starbuck, Hooked on Java, Addison-Wesley Longman, 1996.
Direct questions concerning this article to Ann Wollrath, Sun Microsystems, Inc., Mailstop UCHL03-304, 2 Elizabeth Dr., Chelmsford, MA 01824-4195; [email protected].
Ann Wollrath is a senior staff engineer with JavaSoft, where she is the lead designer and project lead of the Java Remote Method Invocation system. Prior to joining JavaSoft, she researched reliable, large-scale distributed systems in Sun Microsystems Laboratories and parallel computation at MITRE Corporation.
WWW BROWSERS!
The IEEE Computer Society maintains a home page on the World Wide Web that gives you information on membership, publication subscription, conferences, and career opportunities. Look for magazine information such as abstracts, selected articles and columns, author guidelines, and copyright information. Access the Computer Society home page at
IEEE Micro especially welcomes you and asks for your impressions of its latest issue. Let the editors know if Micro is serving your needs.
To go directly to Micros home page:
http://www.computer.org
http//:www.computer.org/pubs/ micro/micro.htm
May/June 1997 53