Sie sind auf Seite 1von 89

Java RMI

Introduction to RMI

Warning
This course is very volatile. Software is upgraded every semester. You should not assume that an example in the presentation is complete, or that it will work in the present environment. It is best to get your code examples from the Sun Java tutorials and modify them to work. Use the lectures to understand the general principles.

Java
Java is a general purpose Object-Oriented language Java provides a number of features that support development of GUI applications and client/server applications over local and wide area networks (RMI and JDBC).

Remote Method Invocation (RMI)


RMI is a distributed computing technology RMI enables networked application collaboration via remote method proxies Interfaces implemented by the server object are instantiated in clients, where its methods are invoked as proxies to the servers. RMI services are available through the java.rmi, java.rmi.server, and java.rmi.registry packages

Key RMI Participants


RMI Registry

2
Java Client Client code 7 Remote Interface 3

1
Java Server Server 5 Implementation Remote Interface

4
Network

High-Level RMI Sequence


1. 2. 3. 4.
5. 6. 7.

Server registers its interface in the RMI registry Client queries registry for remote interface Client implementation invokes interface object The interfaces inherited classes marshal invocation parameters to network packets The Server implements the interfaces methods The Server returns its result to the network The Client is issued the result

The Remote Interface (1)


Care must be taken in designing remote interfaces
Consider how to best balance computation and communication between nodes Many calls to remote methods with small argument sizes is network inefficient Few calls to remote methods with heavy computational needs incurs client latency

The Remote Interface (2)


method computation time sluggish client, burdened server
balanced client and server responsive client, underutilized server remote message size

The Remote Interface (3)


The interface extends the java.rmi.Remote interface The interface must be public An example interface
public interface MyIntf extends Remote

Interface Methods (1)


The interfaces methods:
Not all parameters and return types are remote-able The arguments class or type must be serializable A class is serializable if it implements the java.io.Serializable interface The method must declare java.rmi.RemoteException in its throws clause

Interface Methods (2)


An example method declaration:
public Boolean MyMethod (int Key) throws RemoteException;

The Remote Server (1)


The remote interface needs to be embedded in a server class so that its implementation can be defined The Server class extends the java.rmi.server.UnicastRemoteObject and implements the user-defined interface example:
public class Server extends implements MyIntf UnicastRemoteObject

The Remote Server (2)


Constructors for remote objects must provide a default constructor that calls super() All methods, including the constructor, must declare java.rmi.RemoteException in its throws clause Example:
Server() throws RemoteException { super(); }

The Remote Server (3)


Implement the remote interfaces methods As before, all methods must throw RemoteException Example:
public Boolean MyMethod (int Key) throws RemoteException { method implemenetation here }

The Remote Server (4)


The remote class is instantiated, either via a static main() method, or from some other class to execute. The remote object typically requires a security manager to ensure that any classes being transferred to it (via its method calls for example) are valid. The remote object need to be registered in the RMI registry so it can be located by clients.

The RMI Registry (1)


The RMI registry is a service that typically runs on the servers node. It is used to help the client find the remote objects reference so that it can invoke its methods. The server registers itself with the RMI registry by giving itself a well-known-name

The RMI Registry (2)


Registration of the server object is done via the java.rmi.Naming class and its bind() or rebind() methods. Example:
Server server = new Server(); Naming.rebind(MyServer", server);

This process makes the server object reference available to clients.

The RMI Registry (3)


To bind to a different protocol port, for example 2001, use:
Naming.rebind(//afsXX.njit.edu:2001/MyServer", server);

The Security Manager (1)


Security manager guarantees that the classes that get loaded perform only allowed operations. If no security manager is specified, no class loading, by RMI clients or servers, is allowed, aside from what can be found in the local CLASSPATH. A security manager is required in any JVM that needs to download code, and RMI clients need to download RMI stubs (as well as any other custom classes or interfaces needed to communicate with the RMI server).

The Security Manager (2)


Creating a policy file for the security manager The server requires a policy file that is provided by the command-line invocation of the JVM to declare the process privileges Example:
grant { permission java.net.SocketPermission hostname:1024-65535","connect,accept"; permission java.net.SocketPermission hostname:80", "connect"; };

The Client (1)


The client needs to find the RMI registry so that it can locate remote-able objects. After finding the registry, it can search for a specific object by the name it was registered with by the server. The RMI registry finds the object reference of the named object, and returns it to the client. The client invokes methods on the remote object reference.

The Client (2)


Find an RMI Registry service Use the java.rmi.registry.LocateRegistry class to locate the registry with the getRegistry() method. getRegistry can be called with a hostname if it is located on a node different than that the client is running. Example:
Registry registry = LocateRegistry.getRegistry(hostname);

The Client (3)


To locate a specific object in the registry, one uses the Registry method lookup(). Pass the name of the object to the lookup method. Example
Server server = (Server)registry.lookup(MyServer");

The type needs to be casted to the servers type as shown here (Server)

The Client (3)


The client can now make remote object reference method calls. Exceptions need to be caught. Example:
try { server.MyMethod(keyValue); } catch (IOException e) { ; } catch (Exception e) { ; }

Running the Registry, Server, and Client


The RMI registry needs to be running first to be able to both accept registrations from servers and queries from clients. Servers need to be running before the client (some advanced uses of the registry allow automatic server starting). Finally, clients can be started.

Starting the RMI Registry


Starting the registry on a UNIX server: rmiregistry & Starting on Windows: start rmiregistry
To start on a port other than the default port of 1099; for example port 2001: rmiregistry 2001 &

Starting the Server and Client

Need to supply a command line directive to indicate the security policy file.
java -Djava.security.policy=policy Server java -Djava.security.policy=policy Client

Tools to examine your network messages


You can look at the messages you are sending across the network. If you are using Eclipse with the RMI plug-in, it has a tool called RMI spy. If you are passing a message across a network your laptop is logged on to, you can use Wire Shark. Note that if you are doing both your client and server on the University Computer Systems, you might not be able to use a network sniffer.

Bringing it all Together


What follows is an example RMI client-server application that demonstrates the previous concepts. The application is an emulated biometric authentication system.
Purpose is to read a users eye image and compare it to a database to see if the user has access privileges to the server.

An Emulated Biometric Authentication System

Key Actions of the System


1. An image of the users eye is presented to a Client for processing 2. The eye image is encoded by an algorithm to create a signature 3. The Client passes the signature to the Server via a Java Remote Method Invocation 4. A Server listens for remote client requests to be authenticated. Upon reception, the Server compares the offered signature to those in its database. If there is a high correlation ( 95%), the user is granted access

Key Actions of the System (2)

5.
6. 7. 8.

Three representative eye images are used to denote trusted users of the system Eye images are encoded by a radial signature algorithm The signatures derived from the images are stored in an array within the Server for comparison Validation requests are either accept or denied based on the comparison results of step 4

UML Model of the Design

Eye Signature Algorithm (1)


To authenticate the eye, a signature is derived from its image The signature of the Clients eye is compared against a database Because the image of the Client and its image on the server might be slightly different, some fuzziness is necessary in the evaluation to allow close, but not perfect matches

Eye Signature Algorithm (2)


For this demo, a simple eye signature algorithm radially samples the eye image as shown. 500 samples are taken around the eye image. Samples are stored in an int[] array.

The Remote Interface (1)


Lets assume this Server is to serve many Clients.
How should the load be distributed? Deriving a signature from the eye image requires image processing which can be expensive.

We choose to balance the compute and communications overhead by processing the eye image at the Client and only send its signature to the Server instead of the whole image.

The Remote Interface (2)


The interface shall transport an eye signature as an integer array to the Server for authentication The Validation.java interface file:
package cs633rmi; import java.rmi.*; public interface Validation extends Remote { public Boolean Validate (int[] sig) throws RemoteException; }

Image Processing (1)


An Image class is created to aid both the Client and Server classes. This Image class can derive and store eye signatures, and performs the scoring function to compare eye images. The code for the Image.java file follows.

Image Processing (2)


package cs633rmi; import java.awt.image.*; import java.io.*; import javax.imageio.*; import java.lang.Math.*;
public class Image { final int NUM_EYES = 3; final int NUM_SAMPLES = 500;

Image Processing (3)


BufferedImage[] img = new BufferedImage[NUM_EYES]; int[][] signature = new int[NUM_EYES][NUM_SAMPLES]; // Initialization method public void Init() { // Initialize array elements for (int i=0; i<NUM_EYES; i++) { img[i] = new BufferedImage(100, 100, BufferedImage.TYPE_BYTE_GRAY); } }

Image Processing (4)


public void LoadDatabase() { try { img[0]=ImageIO.read(new File("eye1.jpg")); img[1]=ImageIO.read(new File("eye2.jpg")); img[2]=ImageIO.read(new File("eye3.jpg")); } catch (IOException e){System.out.println(e);} // Analyze eye and derive its "signature". for (int i=0; i<NUM_EYES; i++) { signature[i] = DeriveEyeSignature(img[i]); } }

Image Processing (5)


public int[] DeriveEyeSignature(BufferedImage eye) { // Find center of the image. int cx = eye.getWidth(null)/2; int cy = eye.getHeight(null)/2; int x, y, sample; double r = 0.0; double theta = 0.0; int[] sig = new int[NUM_SAMPLES];

Image Processing (6)


// This loop is the radial sampler. for (int count=0; count<NUM_SAMPLES; count++) { r=r + 0.25; theta = theta + 0.075; x=(int)(r*java.lang.Math.cos(theta)+cx); y=(int)(r*java.lang.Math.sin(theta)+cy); // Sample, and mask to byte-width. sample = eye.getRGB(x, y) & 0xFF; sig[count++] = sample; } return(sig); }

Image Processing (7)


public double[] Score(int[] sig) { double tmp_score; double score[] = new double[NUM_EYES]; for (int i=0; i<NUM_EYES; i++) { tmp_score = 0.0; for (int j=0; j<NUM_SAMPLES; j++) { if (java.lang.Math.abs(sig[j]signature[i][j])<13) tmp_score++; } score[i]=tmp_score/(double)(NUM_SAMPLES); } return(score); }

Image Processing (8)


public int NumEyes() { // Returns the number of eyes. return NUM_EYES; }
public int NumSamples() { // Returns the number of samples per eye. return NUM_SAMPLES; }

The Client (1)


For this demo, the Client reads an eye image from a file to emulate scanning a users eye. The Client uses the java.imageio and java.awt.image packages to simplify graphics file reading. The Client takes single command line argument for the hostname where the RMI registry is running. The Client.java file code follows:

Client (2)
package cs633rmi;
import import import import import import java.io.*; javax.imageio.*; java.awt.image.*; java.rmi.registry.LocateRegistry; java.rmi.registry.Registry; cs633rmi.Validation;

public class Client {

Client (3)
public static void main(String args[]) { if (System.getSecurityManager() == null) { System.setSecurityManager(new SecurityManager()); } try { Registry registry = LocateRegistry.getRegistry(args[0]); Validation v = (Validation) registry.lookup("Validator");

Client (4)
Image img = new Image(); img.Init();
BufferedImage eye = new BufferedImage(100, 100, BufferedImage.TYPE_BYTE_GRAY); eye = ImageIO.read(new File(args[1])); // Derive this eye's signature. int [] signature = new int[img.NumSamples()]; signature = img.DeriveEyeSignature(eye);

Client (5)
// Pass this signature to the remote server for authentication.
// Perform the RMI call here Boolean b = v.Validate(signature); if (b) System.out.println(Authenticated."); else System.out.println(Denied access."); }

Client (6)
catch (IOException e) { System.out.println(e); } catch (Exception e) { System.out.println(e); } } }

The Server (1)


The Server implements the Validation remote interface. The Server initializes itself and reads the eye database to store trusted users. The Server registers itself in the RMI registry in its main() method. The Server then waits for Validate() method calls from the Validation remote interface. The Server.java file code follows:

The Server (2)


package cs633rmi;
import import import import java.rmi.*; java.rmi.server.*; java.awt.image.*; cs633rmi.Image.*;

public class Server extends UnicastRemoteObject implements Validation {

The Server (3)


Image img; Server() throws RemoteException { super(); // Create an Image object that performs the eye image processing. img = new Image(); img.Init(); img.LoadDatabase(); System.out.println("There are "+img.NumEyes()+" eyes in the database."); }

The Server (4)


public Boolean Validate(int[] eyeSignature) throws RemoteException { System.out.println("Validating eye..."); // Create a scoring array for the comparisons. double[] score = new double[img.NumEyes()];
// Perform scoring use "fuzzy" Hamming distance. score = img.Score(eyeSignature);

The Server (5)


// Report scores and find the greatest. int whichOne = -1; double greatest = 0.0; for (int i=0;i<img.NumEyes(); i++) { System.out.println(" score[" + i +"] = " + score[i]); if (score[i] > greatest) { greatest = score[i]; whichOne = i; } } System.out.println("eye[" + whichOne + "] was the best match.");

The Server (6)


// If the greatest value is more than 95% confidence, then admit. if (greatest >= 0.95) { System.out.println("Match is >= 95% confidence - admitted."); return true; } else { System.out.println("Match is < 95% confidence - denied."); return false; }
}

The Server (7)


public static void main(String[] args) { if (System.getSecurityManager() == null) { System.setSecurityManager(new SecurityManager()); } try { Server server = new Server();
Naming.rebind("Validator", server); System.out.println("Server is bound to registry."); }

The Server (8)


catch (Exception e) { System.err.println("Server error:"); e.printStackTrace(); }
} }

Running the Demonstration


This demonstration shows the system running on two AFS servers through two different ssh shells. In addition to the Java class files, a security policy file, called policy is needed and several eye images.

Eyes

eye1

eye2

eye3

eyeX

Eyes 1, 2, 3 are trusted at the server. Eye X is unknown to the server. Another eye, called eye2withnoise.jpg is eye2 with noise to emulate a real system.

Running the Demonstration (2)

On one ssh console, start the RMI registry.


rmiregistry &

On the same ssh console, start the Server.


java Djava.security.policy=policy cs633rmi.Server

On the other ssh console, start the client.


java Djava.security.policy=policy cs633rmi.Client barenboim [eye2.jpg, eye2withnoise.jpg, unknown.jpg]

The Client Console

The Server Console

Demo Discussion
The screenshots on the previous slides show three test cases
Eye 2 shows a perfect match (1.0) at index 1 (the second eye). Eye 2 with noise shows that eye 2 in the server is still a 96% match, thus allowing it access. Unknown shows no correlation above 95%, thus, it is denied access.

RMI Security
One of the most common problems encountered with RMI is a failure due to security constraints. The security policy can be set by constructing a SecurityManager object and calling the setSecurityManager method of the System class. The SecurityManager class has a large number of methods whose name begins with check. For example, checkConnect (String host, int port).

Security Continued
If the current security policy does not allow connection to this host and port, then the call throws an exception. This usually causes the program to terminate with a message such as: java.security.AccessControlException: access denied (java.net.SocketPermission 127.0.0.1:1099 connect,resolve)

Java-RMI vs. CORBA and DCOM


Java-RMI is a Java-specific middleware spec that allows client Java programs to invoke server Java objects as if they were local. Java-RMI is tightly coupled with the Java language.

Comparison Continued
Since Java-RMI is tightly coupled with The Java Language, Java-RMI can work with true sub-classes. Because of this, parameters passed during method calls between machines can be true Java Objects. This is impossible in DCOM or CORBA at present.

Comparison Continued
If a process in an RMI system receives an object of a class that it has never seen before, it can request that its class information be sent over the network. Over and above all this, Java-RMI supports Distributed Garbage Collection that ties into the local Garbage Collectors in each JVM.

Garbage Collection
The Java Virtual Machine has an automatic garbage collector that will reclaim the memory from any object that has been discarded by the running program. Garbage collection is difficult if the server and client run on different machines. The RMI subsystem implements a reference counting-based distributed garbage collection (DGC) algorithm to provide automatic memory management facilities for remote server objects.

How DGC works


The remote server keeps track of all external client references. When a reference is made, the server increases the object reference count by one and marks the object as "dirty". When a client drops the reference, the DGC decreases its reference count by one and marks the object as "clean." When the reference count reaches zero, the remote object is free of any live client references. It is then placed on the weak reference list and subject to periodic garbage collection.

Advantages of RMI
Object-Oriented Safe and Secure Easy to Write/Easy to Use Connects to Existing/Legacy Systems (JNI) Write Once, Run Anywhere Distributed Garbage Collection Parallel Computing

RMI Limitations
RMI is not full featured middleware No mechanism for object description No server events Java only, not language independent Firewalls are not supported Naming service is not persistent No load balancing

Summary
Java RMI is a distributed object model for the Java platform. RMI extends the Java object model beyond a single virtual machine address space. RMI uses object serialization to convert object graphs to byte streams for transport.

Trouble Shooting
Default port for RMI RegistryImpl is 1099. If it is already in use, you will get a
java.net.SocketException: Address already in use.

Do not try to use the loopback address, 127.0.0.1 improperly. It does not work if you have a network card installed on your computer. RMI is subject to Connection Exceptions that are idiosyncratic and difficult to overcome. This is one of the most common topics in RMI discussions.

Problems Encountered
A java.rmi.NotBoundException was overcome by bypassing the start command and starting the server directly. This is not recommended, as the program will not exit normally. NOTE: A probable cause is another version of Java on the system that is referenced by the start command. Several java.rmi.UnmarshallException were caused by classes not in the class path. Some students just had to add the current directory: set classpath=.%classpath%

ClassNotFoundException
Exception: java.rmi.ServerException: RemoteException occurred in server thread; nested exception is: Caused by: java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is: Caused by: java.lang.ClassNotFoundException: ChatServerImpl_Stub

Root cause:
Did not specify the codebase property as one of the VM arguments

Solution:
Pass codebase property to java interpreter java Djava.rmi.server.codebase=http://web.njit.edu/~gblank/rmi/b in/ChatServerImpl

NoClassDefFoundError
Exception: Exception in thread "main" java.lang.NoClassDefFoundError: com/is/chat/ChatServerImpl Root cause: Failed to run the client from the deployment directory /afs/cad/u/g/b/gblank/public_html/rmi/bin Solution: Change directory

Connection refused error


Exception:
Error occuredConnection refused to host: afs10.njit.edu; nested exception is: java.net.ConnectException: Connection refused

Solution: Start rmi registry and register the server class before running the client

Hints
When you have a problem, you may have to kill all your processes and restart everything. You must start the registry (Windows command) start rmiregistrystart All remote interfaces must extend java.rmi.RemoteInterface, and all remote objects must extend java.rmi.UnicastRemoteObject. Security management and implementing class policies are complex and difficult in RMI. The client policy file permits connection to a specific referenced port number.

Lessons Learned
You can get a trace of the server activity using
java -Djava.rmi.server.logCalls=true <YourServer>

Properties beginning java.rmi.* are part of published RMI spec and docs, while sun.rmi.* indicates things that may vary. You can find the host name of a caller of a remote method with
java.rmi.server.RemoteServer.getClientHost

On a server with multiple host names, you need to force a fully qualified host name with
java.rmi.server.useLocalHostname=true

Environment Conflicts
If you may have multiple versions of Java on your system, try java -version to see which version your environment defaults to. Remember that different versions seldom work together, and that your Windows autoexec.bat file may set some environment values that you might not think about.

Good RMI explanation


The example from the Sun Web site is difficult to get working, because it includes a lot of material that goes beyond the basics. You may wish to find a simpler example. One excellent one was at
http://www.ccs.neu.edu/home/kenb/com3337/rmi_tut.ht ml

RMI Versions (1)


Java 2 SDK, Version 1.6 adds Dynamic Generation of Stub classes, thus removing the need for using the RMI compiler. Java 2 SDK, Version 1.5 adds SSL/TLS Secure Sockets Layer capabilities for RMI.

RMI Versions (2)


Java 2 SDK, version 1.4 adds server-side stack trace retention, Service Provider Interface for RMIClassLoader and Dynamic Server Host Name. Java 2 SDK, version 1.3 adds enhancements to serialization Java 2 SDK, version 1.2 adds activation, the use of custom socket protocols and security policies. Java 1.1 added core RMI support, but usually requires running applets in the applet viewer. Java 1.0.2 was an interim release, and should not be used for RMI.

References
Andrew Tanenbaum and Martin van Steen, Distributed Systems, Prentice Hall, 2002 http://java.sun.com/j2se/1.4.2/docs/guide/rmi/getstart.d oc.html http://developer.java.sun.com/developer/onlineTraining /rmi/RMI.html http://java.sun.com/j2se/1.4/docs/relnotes/features.htm l http://java.sun.com/marketing/collateral/javarmi.html

References (2)
http://java.sun.com/javase/6/docs/technotes/guides/rmi/relnotes. html http://www.javacoffeebreak.com/articles/javarmi/javarmi.html Sun Microsystems, http://java.sun.com/developer/codesamples/rmi.html Vaclav Matyas Jr., Zdenek Riha, Biometric Authentication Systems, Faculty of Informatics, Masaryk University, November 2000.

References (3)
Eye images
http://buytaert.net/cache/images-miscellaneous-2006eye-500x500.jpg http://www.inkycircus.com/photos/uncategorized/2007/ 04/25/eye.jpg http://van-der-walt.blogspot.com/2007/09/how-eyeworks.html http://michelemiller.blogs.com/marketing to women/eye.bmp

Das könnte Ihnen auch gefallen