vs7.1.5

Werbung
7.1.5 Java RMI – Remote Method Invocation
(http://java.sun.com/products/jdk/rmi)
(http://java.sun.com/j2se/1.3/docs/guide/rmi/spec/rmiTOC.html)
bietet leider nur begrenzte Verteilungsabstraktion
Unterstützung von Fernaufrufen durch Bibliothekspakete
java.rmi
java.rmi.server
java.rmi.registry
und weitere . . .
7.1.5.1 Elementare Fernaufruf-Programmierung

interface Remote:
Für fernaufrufbares Objekt und sein Vertreterobjekt muß
gemeinsame Schnittstelle definiert werden, die von
java.rmi.Remote erben muß, z.B.
import java.rmi.*;
interface RemoteService extends Remote {
String echo(String s) throws RemoteException;
}
Spätere Vertretererzeugung gelingt nur dann, wenn die Ausnahme
java.rmi.RemoteException vereinbart wird.

class UnicastRemoteObject:
Klasse eines fernaufrufbaren Objekts muß von
java.rmi.server.UnicastRemoteObject erben, z.B.
import java.rmi.*;
import java.rmi.server.*;
class
Server extends UnicastRemoteObject
implements RemoteService {
public String echo(String s) {return s+s;}
public Server() throws RemoteException { }
}
UnicastRemoteObject redefiniert die Operationen von Object
und registriert das fernaufrufbare Objekt bei der RMI-Verwaltung.
Achtung: Ein Server-Objekt kann durchaus auch lokal benutzt werden.
 class Naming:
Namensdienst ist über statische Operationen der Klasse
java.rmi.Naming erreichbar:
public static void rebind(String name, Remote object)
throws RemoteException,
MalformedURLException // java.net
public static Remote lookup(String name)
throws NotBoundException,
RemoteException,
MalformedURLException
erfordert Casting
RemoteService s = (RemoteService)Naming.lookup(...);
(weitere Operationen: bind, unbind, list )
Der jeweilige Name ist wie folgt im URL-Format anzugeben:
[ // host [ : port ] / ] name
Adresse des Namensdienstes
Standard-Host = lokale Station
Standard-Port = 1099
Der Namensdienst wird (unter Unix) gestartet mit
rmiregistry [ port ] &
(und sollte – wenn nicht mehr benötigt – mit kill beendet werden)
Achtung: Inhalt verändern nur lokal, Inhalt befragen auch entfernt !
7.1.5.2 Vertretererzeugung und -installation
Vertretergenerator heißt RMI Compiler und wird aufgerufen mit
rmic <remoteServerClass>
also z.B.
rmic Server
( - nicht mit Schnittstelle RemoteService !)
und generiert bereits übersetzte Stubs:
Eingabe
Ausgabe
Server.class
Server_Stub.class (Vertreter)
Server_Skel.class (Treiber)
Einfaches Beispiel (s.o.):
import java.rmi.*;
import java.rmi.server.*;
interface RemoteServer extends Remote {
String echo(String s) throws RemoteException;
}
class Server extends UnicastRemoteObject
implements RemoteServer {
public String echo(String s) {return s+s;
public Server() throws RemoteException {
}
}
public static void main(String[] arg) throws Exception {
Server s = new Server();
Naming.rebind("Server", s);
}
}
class Client {// start:
java Client <serverHost> <text>
public static void main(String[] arg) throws Exception {
RemoteServer server =
(RemoteServer)Naming.lookup("//"+arg[0]+"/Server");
String text = server.echo(arg[1]);
System.out.println(text);
System.exit(0); // prevent hangup due to RMI threads
}
}
Installation der .class-Dateien:
CLASSPATH geeignet setzen!
 Beim Erzeugen des fernaufrufbaren Objekts muß der zugehörige
Treiber-Code greifbar sein.
 Beim Registrieren des fernaufrufbaren Objekts beim Namensdienst
muß der zugehörige Vertreter-Code greifbar sein
- denn Vertreter-Objekt samt Code wird zum Namensdienst geschickt.
 Beim Erzeugen des Vertreter-Objekts beim Klienten
- als Folge der Anfrage beim Namensdienst –
muß dort der Vertreter-Code greifbar sein.
(Alternative: Namensdienst liefert Vertreter-Objekt samt Code (s.o.)
- sofern Security Manager das Herunterladen erlaubt; vgl. 7.2)
Einfaches Szenario:
Entwicklungs-Station
Klienten-Station
Anbieter-Station
>javac test.java
>rmic Server
(test.java
RemoteServer.class
Client.class
Server.class
Server_Stub.class
Server_Skel.class)
(Client.class
RemoteServer.class
Server_Stub.class)
(Server.class
RemoteServer.class
Server_Stub.class
Server_Skel.class)
>rmiregistry &
>java Server &
>java Client elfe bla
blabla
>
7.1.5.3 Verweise in Fernaufruf-Parameten
Übergeben wird entweder Vertreter oder Kopie des Objekts:

Schnittstelle des formalen Parameters erbt von Remote:
aktueller Parameter muß
(statisch) gleiche Schnittstelle implementieren,
(dynamisch) von UnicastRemoteObject erben,
andernfalls MarshalingException
 Vertreterobjekt wird übergeben

Schnittstelle des formalen Parameters erbt nicht von Remote:
aktueller Parameter muß
(statisch) gleiche Schnittstelle implementieren,
(dynamisch) Schnittstelle java.io.Serializable implementieren,
andernfalls MarshalingException
 Objektkopie wird übergeben
In Objekte eingebettete Verweise werden entsprechend behandelt.
Felder (arrays) und Zeichenketten (strings) sind serializable !
Achtung!
Wenn ein formaler Parameter einen Schnittstellentyp hat, kennt man
vom aktuellen Parameter nur diese Schnittstelle (unabhängig davon,
ob es sich um einem lokalen oder einen Fernaufruf handelt).
Wird ein fernaufrufbares Objekt (7.1.5.1) übergeben, so weiß man nicht,
ob das Objekt tatsächlich entfernt oder aber lokal vorliegt.
Handelt es sich um ein serialisierbares Objekt, so wird in Abhängigkeit
von seiner Lage entweder eine Kopie oder das Objekt selbst geliefert!
 Die Semantik des Aufrufs ist nicht eindeutig bestimmt.
7.1.5.4 Verteilte Speicherbereinigung
wird von Java RMI eingeschränkt unterstützt:
Verwendung von Verweiszählern (reference counts)
und Kooperation mit den lokalen Garbage Collectors
mit Einsatz von Javas schwachen Verweisen (weak references)
Herunterladen