560 likes | 689 Views
Remote Objects. From notes originally prepared by Gareth Lee Department of Electrical and Electronic Engineering, University of Western Australia. Overview. First - look at remote loading of software components Then - adapt the example to use RMI Finally - the RemoteWorker system
E N D
Remote Objects From notes originally prepared by Gareth Lee Department of Electrical and Electronic Engineering, University of Western Australia
Overview • First - look at remote loading of software components • Then - adapt the example to use RMI • Finally - the RemoteWorker system • Using a network of PEs for solving problems • Distributes a task from a master to a set of workers (slaves) • Programmers write a Solver class • Actually solves the problem (or sub-problem) • System handles distribution of these classes • Slaves can be started on remote machines and left running • Network becomes a powerful computing resource!
Example Application - Image viewer • Requirements • Able to display a wide range of image formats • Imaging a picture library • Extensible • Support new image formats without redistributing the entire application • New image decoders prepared by the IT department (or external suppliers) • Allow bug fixes to the existing code without updating every desk machine
Software components • Allows designers to build applications from substitutable (reusable) components • Components can be loaded as they are needed, not when the application is started • Minimizes memory footprint at any time • Maximizes versatility of application • Makes an application extensible • Minimises development cost (by allowing reuse)
Remote Class loading • Remote Class Loading is a half way house • Deploy a simple shell application onto clients’ desks • This shell loads software components on demand from a shared server • Users never need know that this is going on behind the scenes • Demonstrated by the picture viewer example
Implementing components • We need a way of abstracting Java classes • We cannot mention a component class directly otherwise it will be loaded at the outset • An indirect way of creating components • Components must implement agreed interface • We must be able to create a component without hard-coding its name in the source • Here we create a specific family of software component • Java generalizes components as JavaBeans
The ImageCreator interface • We need to create a family of software components that know how to decode various image file formats • ImageCreator is the standard interface for accessing components. . . • . . . so each of the components must implement the interface
The ImageCreator interface /** This provides an interface for components which are able to create image objects from files. @author Gareth Lee @version 0.1, March 11th, 2000. */ public interface ImageCreator { /** Read the contents of the specified source file and create an Image object containing the file contents */ public Image createImage(File source); }
Abstracting Java classes • Java provides us with a pool of objects of type java.lang.Class • These abstract the data types that Java supports • Class types as found in the standard libraries (API classes) • User defined classes • Software components written by users • Built in primitive types • int, boolean, etc
Remote Class Loading • Deploy applications using applets • Overcomes distributions costs for bug fixes and upgrades • Downside: • Most browsers don’t trust applets and impose severe restrictions • Severe UI restrictions when running applets • Difficult to deploy groups of applets which are able to cooperate (for example a word processor and a spell checker)
java.lang.Class • Allows types (classes) to be accessed by name • Strings giving the fully qualified name • Class name must be prefixed by the package in which it is loaded • egjava.lang.Integer • Objects may be created (instantiated) from the instances of the Class • Zero argument construction is trivial • Constructors with arguments a little trickier • java.lang.Class API • Has methods which allow properties of the class type to be obtained • Constructors, fields, methods, etc
java.lang.Class • Constructing (loading) a class • Class forName(String qualifiedName) eg • Class c = Class.forName( “RemoteWorker” ); • Reflection API methods • Object newInstance() // construct obj • Constructor[] getConstructors() • Method[] getMethods() • Field[] getFields() • Class[] getInterfaces()
. . but this is local loading • When we call Class.forName(String) we use the default class loader • The JVM uses objects of type java.lang.ClassLoaderto load classes dynamically • The default loader uses the standard class path • Specified by • Environment variable CLASSPATH • Command line option -classpath
Remote class loading - using HTTP • To load classes from some remote source we must create a new class loader that can load remotely • java.net.URLClassLoader is able to load classes from URLs • Allows us to load classes using the HTTP protocol from any web server
java.net.URLClassLoader • Constructor • URLClassLoader(URL[] classPath) • Useful methods: • Class findClass(String qualifiedName) • Does the same job as Class.forName() • URL[] getURLs() • … and a few others
java.net.URL • Abstracts a universal resource locator • Constructor • URL(String urlName) egnewURL(“http://asp/index.html”) • Methods to take the URL apart, such as • String getHost() • int getPort() • String getPath()
Different ImageCreators • Assume we have different ImageCreator objects available on some remote system • ImageCreator_GIF • Decodes GIF image formats • ImageCreator_JPG • Decodes JPEG format images • ImageCreator_BMP • Decodes (256 colour) MS-Windows Device Independent Bitmap files • We want to be able to download and use the appropriate one on demand
Loading Viewer classes public ImageCreator loadImageCreator(String type) { try { // Get a URL as a text string from ... String urlTextString = sourceURLText.getText(); // Form an array of URLs URL[] sourceURLs = new URL[] { new URL(urlTextString) }; // Construct the class loader URLClassLoader loader = new URLClassLoader(sourceURLs); // Load the class Class componentType = loader.loadClass( "ImageCreator_" + type); // Make an object of the class return (ImageCreator) componentType.newInstance(); } catch (Exception e) { e.printStackTrace(); } }
Exceptions, exceptions! • java.net.MalformedURLException • The (complex) format of the URL is invalid • java.lang.ClassNotFoundException • The class could not be loaded from the remote location • java.lang.ClassCastException • The loaded class does not implement the interface that we require
Remote loading alternative ... • Remote Procedure Calls • Idea has been around for at least 20 years since Sun introduced RPC to SunOS • RPC involves hiding a network communication protocol so that programmers appear to simply be calling procedures • This idea adapts very easily to OO programming as distributed objects
A Little History • IBM lead the way with DSOM (late 80s) • Microsoft developed this into the distributed common object model (DCOM) (ca.1995) • Common Object Request Broker Architecture (CORBA) developed by OMG to provide platform and language independence (1991/94) • Sun developed Remote Method Invocation (RMI) as a simpler alternative (1997)
Remote Method Invocation • First introduced into JDK 1.1 • Java specific protocol aimed at simplicity • Java is already platform independent • Closely linked to the idea of client/server • A server application provides some form of service to zero or more clients • A client program uses the service • A Java interface defines the contract between the two
The Object Registry • Server advertises its services using a service label • A string naming the service • It registers the label with a object registry (rmiregistry) which runs as a daemon • Clients connect to the object registry and ask for the servicethey require • Identifying it with the service label • Clients must know where the object registry is located (unlike in JINI) • Clients obtain a reference to the desired interface and can then call its methods
Loading remote components using RMI • As an alternative we can use RMI to allow us to load remotely • We will look at the following parts: • The service interface • ImageCreatorService • A server implementation class • RMIComponentServer • A client implementation class • RMIClientViewer
RMI versus HTTP • HTTP is really intended for document downloads • Using HTTP POST you can provide parameters as part of a request • Too specific for communication between distributed objects • RMI allows any object to • Call any method in another object (locally or remotely) • Pass any list of parameters (not just Strings) • Receive back any Java type as the return value
The ImageCreatorService interface public interface ImageCreatorService extends java.rmi.Remote { /** Deliver the byte codes for an ImageCreator component which will deal with images of the specified type. */ public byte[] loadClassData(String compName) throws RemoteException; }
The component server • Just a few simple steps to write the server: • STEP ONE: Create a server class which implements your interface and subclasses java.rmi.server.UnicastRemoteObject • STEP TWO: Make the server register itself with the object registry • STEP THREE: Implement the methods cited in the service interface
STEP ONE public class RMIComponentServer extends java.rmi.server.UnicastRemoteObject implements ImageCreatorService { public RMIComponentServer() throws RemoteException { try { java.rmi.Naming.rebind( "rmi://localhost/ImageCreatorService", this); } catch (MalformedURLException mue) { mue.printStackTrace(); } } . . . . STEP TWO Service label The RMIComponentServer class
public byte[] loadClassData(String className) throws RemoteException { // Implementation edited out for brevity. . . } public static void main(String[] args) { try { System.out.println("RMIComponentServer: started."); RMIComponentServer server = new RMIComponentServer(); } catch (Exception e) { e.printStackTrace(); } } STEP THREE The RMIComponentServer class
The client viewer implementation • This is in the form of RMIClientViewer but the interesting part is the inner class called RMIClassLoader • This subclasses java.lang.ClassLoader • The parent of all classes capable loading byte codes • RMIClassLoaderloads byte codes with RMI • Rather than HTTP (as in the previous example) • Distributed memory space (all parameters are passed by value, rather than by reference) • RMI requires a different design discipline
Reliability Issues • When calling a method locally there are only two possible outcomes: • The method succeeds • The method fails with an exception • When calling an RMI method there is a third category: • It was impossible to call the method, since the RMI mechanism failed in some way
How does RMI work? • It uses proxy classes called stubs and skeletons • RMI calls from the client are intercepted by a proxy class called a stub • They are passed to another proxy called a skeleton residing on the server which calls the server class on the client’s behalf • Stubs and skeletons can be generated using rmic
Proxy stubs • Implements the chosen service interface so it looks like the remote server as far as the client is concerned • Packages up (marshals) arguments for dispatch across the network • Sends them using the Java Remote Method Protocol (JRMP) • Waits for and unpacks the return value
Proxy skeletons • Waits for JRMP request to be received from a TCP/IP connection • Unmarshals the arguments and passes them on to server implementation • Awaits a return value and marshals it to be returned through the TCP/IP connection • Not needed by JDK 1.2
Client VM Server VM Client Obj Server Impl. Stub Skeleton TCP/IP link Call x=if.m() int m() { . . . . } Retn Service Interface Service Interface How it all fits together
rmic • Remote interface compiler • Specify your server implementation class as a command line argument eg rmic -classpath . RMIComponentServer • Ascertains the service interfaces • Creates a stub and a skeleton class for each interface eg RMIComponentServer_Stub.class RMIComponentServer_Skel.class • Recreate stubs and skeletons when you modify the interfaces for your server
RMI Method Arguments • What restrictions are there on RMI arguments? • By default parameters are passed by value • NOTE: This is the opposite of the conventions when calling a local method • This is the normal behavior for primitive types: byte, short, char, int, long, float, double, boolean • Objects must be pickled before being sent! • They are marked as implementing the Serializable interface
java.io.Serializable • Contains no methods! • Just amarker for those classes which are may be serialized • Into a file or • Sent across the net to a different VM by RMI • Many Java classes implement java.io.Serializable • Some notable exceptions: Runtime system and Reflection API classes and some I/O classes
Passing objects by reference • It is possible to pass objects be reference, but only if you design them specifically for RMI • STEP ONE: Make the object implement the java.rmi.Remote interface • STEP TWO: Export the object by registering it using methods in java.rmi.Naming • In other words you are turning the object into another RMI server in its own right
Inner class RMIClassLoader • Part of the client side application which wants to load the appropriate viewer class • STEP ONE • Create a reference to the required service interface • STEP TWO • Lookup the service by connecting to the chosen object registry • STEP THREE • Call a method through the interface
public class RMIClassLoader extends ClassLoader { ImageCreatorService remoteService = null; public RMIClassLoader(String serverName) throws NotBoundException, MalformedURLException, RemoteException { remoteService = (ImageCreatorService) java.rmi.Naming.lookup( "rmi://" + serverName + "/ImageCreatorService"); } . . . . STEP ONE STEP TWO sea.picturelib.RMIClientViewer
public Class findClass(String name) throws ClassNotFoundException { try { byte[] byteCodes = remoteService.loadClassData(name); return defineClass( name, byteCodes, 0, byteCodes.length); } catch (RemoteException re) { throw new ClassNotFoundException( "failed to load class " + name + " using RMI"); } } } STEP THREE sea.picturelib.RMIClientViewer
It’s that simple. . . • STEP ONE • Define the service interface • STEP TWO • Write a server that implements the interface • STEP THREE • Make the server register with an object registry • STEP FOUR • Write a client that looks up the desired service in the object registry • STEP FIVE • The client can call methods in its interface
. . . not quite! • Some general RMI issues … • RPC (RMI) can lull the designer into a false sense of security! • Beware! They may look like method calls but they’re really network communications • You will need a design that take into account • Reliability issues • Latency issues
Reliability Issues • When a remote method cannot be called it throws an exception in the java.rmi.RemoteException hierarchy • java.rmi.ConnectionExceptionwhen the network connection could not be established • java.rmi.ConnectionIOExceptionwhen the network connection failed • . . . and there are plenty of things that can go wrong (17 other exception types)
Latency Issues • Calling methods locally • 100% reliable and • only requires a few nanoseconds • Not true for RMI • Network might be congested (or down) • Remote server may be busy (or down) • RMI calls take a long time: • About 1 ms in the best scenario (one million times as long as a local method call!) • Up to a 3 minute time-out • DNS lookup fails
Latency Issues • It is unwise to make RMI method calls from any time-sensitive code • User interface callback handlers • Process/hardware controllers • Control the network environment • Make RMI calls in a separate thread • Design an interface with coarse-grained methods to minimize round trip delays
Accessing remote objects • Why does an object need to be called remotely? • Only because it needs some resource that the remote machine can offer • Some custom peripheral (a scanner?) • CPU/Memory resources • Intimate access to a database • Some other resource that you wish to manage centrally • If not, then copy back the bytes codes and execute locally! • This is starting to sound like JINI
Design Issues • Work out where objects need to be within the system architecture • Why not get the RMI server to support the ImageCreator interface directly? • We could have passed the File object across to the server but not the file! • File implements Serializable • We could need to create a remotely accessible stream object • Must then pass the image object back to the client • It is expensive to transfer large arrays of bytes
Other sources of information • Lots of RMI information at Sun’s site http://www.javasoft.com/products/jdk/rmi • JRMP (RMI’s wire protocol) is described in the downloadable documentation available for each Java 1.2.X or 1.3.X VM or from http://java.sun.com/j2se/1.3/docs/guide/rmi/.. spec/rmi-protocol#60