prr rmi

background image

c

Karbowski, Kozakiewicz, Szynkiewiczowie, 2003

1

Java RMI – Remote Method Invocation

RMI

to podstawowy mechanizm typu RPC w języku

Java

. W przeciwieństwie do Sun RPC jest to

mechanizm w pełni obiektowy i nowoczesny. Nie jest to przy tym jedyne narzędzie tego typu dostępne w
języku Java – można używać także np.

CORBA

.

W przeciwieństwie do RPC czy CORBA, RMI nie wprowadza żadnych nowych elementów wykraczających
poza sam język. Językiem specyfikacji interfejsu jest tu sama Java. Szeregowanie danych odbywa się
przez interfejs, który musi być implementowany przez przekazywane obiekty. W efekcie cały mechanizm
doskonale wplata się w program, nie ma potrzeby sprawdzać, jak zostały przetłumaczone deklaracje typów
z interfejsu, czy inne temu podobne elementy. Jeśli program jest napisany w przemyślany sposób, to poza
inicjalizacją, tzn. pobraniem referencji do pierwszego zdalnego obiektu, w zasadzie nie widać w kodzie, że
używa się zdalnych obiektów.

background image

c

Karbowski, Kozakiewicz, Szynkiewiczowie, 2003

2

Definicja interfejsu w RMI

Interfejs w RMI jest po prostu interfejsem w sensie języka Java. W efekcie niemożliwy jest bezpośredni
zdalny dostęp do pól obiektu, można jedynie wołać jego metody. Jest to zresztą zgodne z duchem zarówno
Javy, jak i mechanizmów RPC.
Każdy interfejs zdalny musi spełniać dwa warunki:

Musi rozszerzać interfejs

java.rmi.Remote

przez dziedziczenie pośrednie lub bezpośrednie.

Wszystkie

jego metody muszą deklarować klauzulą

throws

możliwość rzucenia wyjątku

java.rmi.RemoteException

.

Interfejs nie wymaga żadnej nietypowej obróbki w celu uzyskania właściwego kodu źródłowego, jak w
przypadku IDL (CORBA), czy RPC – wystarczy, że właściwa klasa-serwer implementuje go.
Do obiektów zdalnych odwołuje się przez referencję do odpowiedniego interfejsu. Można też realizować
różne wersje interfejsów i, mając odpowiednią referencję, sprawdzać, którą wersję implementuje operatorem

instanceof

. W rzeczywistości referencja do obiektu zdalnego jest po prostu referencją na skojarzoną z

nim lokalną namiastkę.

background image

c

Karbowski, Kozakiewicz, Szynkiewiczowie, 2003

3

Implementacja klasy serwera

Aby metody obiektu mogły być zdalnie dostępne, musi on spełniać dwa warunki:

Implementować jakiś interfejs zdalny.

Być wyeksportowany.

Eksport obiektu oznacza otwarcie odpowiedniego portu i uruchomienie nasłuchu. Najprościej uzyskać
ten efekt jest dziedzicząc po którejś z podklas klasy

java.rmi.server.RemoteServer

, najczęściej

java.rmi.server.UnicastRemoteObject

. Jeśli nie chce się, lub nie można dziedziczyć po tej kla-

sie, można to zastąpić „owinięciem” obiektu – wyeksportować obiekt, najczęściej w konstruktorze, metodą

static RemoteStub exportObject(Remote obj)

klasy

java.rmi.server.UnicastRemoteObject

(lub odpowiedniej innej). W obu wariantach można wymusić numer portu, lub pozostawić domyślny.
Usługi typu

UnicastRemoteObject

, najstarsze i najczęstsze, są dostępne od momentu ich wyeksporto-

wania do końca programu, lub odeksportowania metodą

static boolean unexportObject(Remote

obj, boolean force)

i przez cały czas muszą być aktywne, tj. rezydować w pamięci. Nie jest to jedyny

typ serwera, wrócimy jeszcze do tego tematu.
Gotowe klasy kompiluje się normalnie, po czym, dla gotowych już klas, wywołuje się generator namiastek

rmic

. Jego argumentem jest nie nazwa pliku, a nazwa klasy, łącznie z pakietem, jeśli jest określony. Dla

klasy

Klasa

z pliku

Klasa.class

zostaną wtedy wygenerowane klasy

Klasa_Stub

i

Klasa_Skel

. Klasa

_Stub

to namiastka dla klienta, będzie mu potrzebna, jak również plik ze skompilowanym interfejsem.

Klient nie musi natomiast mieć plików z klasami samego obiektu zdalnego, ani

_Skel

.

background image

c

Karbowski, Kozakiewicz, Szynkiewiczowie, 2003

4

java.io.Serializable – szeregowanie obiektów

Podczas, gdy obiekty zdalne przekazywane są zawsze przez referencję, czy to jako argumenty, czy
wyniki funkcji w wywołaniach RMI, to przesyłanie obiektów lokalnych w RMI odbywa się przez wartość,
z zastosowaniem operacji szeregowania.
Każdy obiekt, który ma być przekazywany przez RMI powinien implementować (

implements

) interfejs

java.io.Serializable

. Interfejs ten nie zawiera żadnych metod, nie trzeba więc robić nic więcej. Jego

implementacja to jedynie zgoda na szeregowanie danego obiektu. Oczywiście klasy pochodne również
będą szeregowalne. Istotne jest natomiast ograniczenie w drugą stronę: klasę można zadeklarować jako

Serializable

tylko, jeśli jej nadklasy bez tej własności mają nieprywatny konstruktor bezparametrowy.

W tym przypadku szeregowane będą dostępne pola tej nadklasy, a więc nie prywatne – te zostaną
zrekonstruowane po drugiej stronie przez konstruktor.
Jeśli potrzebne jest nietypowe szeregowanie, można je osiągnąć implementując ten interfejs oraz definiując
następujące metody:

private void writeObject(java.io.ObjectOutputStream out)

throws IOException

private void readObject(java.io.ObjectInputStream in)

throws IOException, ClassNotFoundException;

w praktyce taka potrzeba nie powinna jednak wystąpić.
W wypadku napotkania przy szeregowaniu dynamicznej struktury danych na nieszeregowalny obiekt,
rzucany jest wyjątek

java.io.NotSerializableException

.

background image

c

Karbowski, Kozakiewicz, Szynkiewiczowie, 2003

5

rmiregistry – rejestracja serwerów. Fabryki obiektów.

Ostatnim nierozwiązanym problemem jest nawiązywanie łączności między klientem a serwerem. RMI
dysponuje w tym celu rejestrem serwerów, uruchamianym poleceniem

rmiregistry

. Rejestr ten zapewnia

bardzo proste wyszukiwanie serwisów na podstawie nazwy.
Serwis identyfikowany jest na podstawie URL o postaci

[rmi:]//<komputer>[:<port>]/<nazwa

usługi>

, np.

//komputer.w.domenie.pl/MojSerwer

, czy

rmi://127.0.0.1/Zegar

. Pominięcie

nazwy komputera oznacza

localhost

, a port domyślny to 1099.

Uwaga:

to rzeczywiście URL, w efekcie

metody wyszukiwania i rejestrowania nazw mogą rzucić

MalformedURLException

.

Do obsługi rejestracji w

rmiregistry

służą statyczne metody klasy

java.rmi.Naming

(uwaga na

pominięte klauzule

throws

!):

1.

public static void bind(String name, Remote obj)

rejestruje nazwę

name

, o ile jest

wolna, kojarząc ją z obiektem

obj

;

2.

public static void unbind(String name)

wyrejestrowuje nazwę;

3.

public static void rebind(String name, Remote obj)

zmienia obiekt skojarzony z nazwą

na nowy;

4.

public static String[] list(String name)

podaje tablicę zarejestrowanych nazw (

name

jest w tym przypadku tylko URLem rejestru, bez nazwy serwisu);

background image

c

Karbowski, Kozakiewicz, Szynkiewiczowie, 2003

6

5.

public static Remote lookup(String name)

wyszukuje serwis o podanej nazwie i zwraca

referencję do niego. Uwaga: tylko dlatego, że to wywołanie nie zawiodło, nie należy zakładać, że
otrzymana referencja jest tą poszukiwaną! Pod daną nazwą może być zarejestrowany zupełnie inny
serwis. Pomocny tu jest operator

instanceof

.

Rejestr RMI jest bardzo prosty, a jednocześnie rzadko wykorzystywany. Typowy program RMI korzysta z
niego tylko raz, w celu początkowego nawiązania łączności. Stosuje się tu mechanizm

fabryki

: rejestrowany

jest jeden obiekt, którego metody tworzą na żądanie odpowiednie obiekty – serwery różnych usług
– i zwracają referencje do nich. Te obiekty mogą potem tworzyć następne, itp. Referencja zdalna
może być przekazywana między komputerami, więc dowolne dwa obiekty mogą wymienić informację o
położeniu trzeciego. Ponieważ składniowo nie różni się to niczym od zwykłego przekazywania referencji do
obiektów lokalnych, od momentu uzyskania pierwszej zdalnej referencji RMI staje się właściwie przejrzyste
dla programisty, o ile pominąć konieczność łapania

RemoteException

i jeśli wszystkie zdalne obiekty

eksportują się już w konstruktorze.

background image

c

Karbowski, Kozakiewicz, Szynkiewiczowie, 2003

7

RMI a zarządzanie pamięcią

Choć RMI jest proste w użyciu, jego protokół jest bardzo złożony. Główną tego przyczyną jest rozproszone
zwalnianie pamięci (distributed garbage collection).
Dla każdego obiektu zdalnego utrzymywany jest licznik zdalnych referencji. Protokół RMI zapewnia
odpowiednią jego aktualizację. Obiekty zdalne mogą być zniszczone dopiero, kiedy nie ma do nich ani
zdalnych, ani lokalnych referencji.
Aby serwer np. kończył sam pracę, kiedy nie jest już potrzebny, przydatna może być informacja o zniknięciu
ostatniej zdalnej referencji. W takiej sytuacji serwer powinien implementować interfejs

Unreferenced

,

zawierający tylko jedną, bez parametrową metodę

unreferenced()

, którą można wypełnić wedle uznania,

a która jest wywoływana przez RMI w momencie stwierdzenia opróżnienia listy referencji do danego obiektu.

background image

c

Karbowski, Kozakiewicz, Szynkiewiczowie, 2003

8

Zaawansowane możliwości RMI

Tunelowanie przez HTTP

– RMI jest w stanie zapewnić łączność nawet w przypadku zablokowania łączności

bezpośredniej przez np. firewall. W tym przypadku można skorzystać z protokołu HTTP.

Ściąganie namiastek

– RMI może automatycznie ściągać namiastki serwerów, z których chce korzystać.

Wymaga to co prawda nieco więcej pracy (trzeba m.in. utworzyć menedżera bezpieczeństwa), ale może
się przydać, choć rzadko w obliczeniach równoległych.

Uruchamianie serwisów na żądanie

– już od wersji 1.2 Javy dostępny jest obok

java.rmi.server.Unicast-

RemoteObject

także serwer

java.rmi.activation.Activatable

. Klasa ta, wraz z zestawem klas

pomocniczych, zapewniają w dość skomplikowany sposób uruchamianie serwisów na żądanie. W szcze-
gólności oznacza to, że referencje zdalne mogą zachowywać ważność po zniszczeniu obiektu, do którego
się odwoływały, a nawet po restarcie maszyny wirtualnej, na której się znajdował, co nie ma miejsca dla

UnicastRemoteObject

.

Użycie CORBA

– RMI korzysta z własnego protokołu JRMP (Java Remote Method Protocol). Od wersji

1.2 Java zawiera jednak ORB i może używać oprócz RMI także CORBA. W wersji 1.3 pojawiło się nowe
narzędzie – RMI over IIOP (Internet Inter-ORB Protocol). Dzięki nowym opcjom

rmic

można napisać

interfejs RMI, a następnie wygenerować namiastki i szkielety używające CORBA, a także odpowiedni plik
w języku IDL.

background image

c

Karbowski, Kozakiewicz, Szynkiewiczowie, 2003

9

Prosty przykład programu

interfaces.java

interface Factory extends java.rmi.Remote {

Server get() throws java.rmi.RemoteException;

}

interface Server extends java.rmi.Remote {

void hello(Client me) throws java.rmi.RemoteException;
void forget() throws java.rmi.RemoteException;
String say() throws java.rmi.RemoteException;

}

interface Client extends java.rmi.Remote {

String what() throws java.rmi.RemoteException;

}

background image

c

Karbowski, Kozakiewicz, Szynkiewiczowie, 2003

10

implementations.java

import java.lang.*;

class theFactory implements Factory {

theFactory() throws java.rmi.RemoteException
{

java.rmi.server.UnicastRemoteObject.exportObject(this);

}

public Server get() throws java.rmi.RemoteException
{

return new theServer();

}

public static void main(String args[])
{

try {

theFactory maker = new theFactory();
java.rmi.Naming.rebind("//127.0.0.1/Fabryka",maker);
System.out.println("Fabryka zarejestrowana");

background image

c

Karbowski, Kozakiewicz, Szynkiewiczowie, 2003

11

}
catch (Exception e) {

System.out.println("Nie zarejestrowano fabryki! Wyjątek: "

+ e.getMessage() );

}

}

}

class theServer implements Server {

Client he;

theServer() throws java.rmi.RemoteException
{

he = null;

System.out.println("Nowy serwer!");

java.rmi.server.UnicastRemoteObject.exportObject(this);

}

public void hello(Client me) throws java.rmi.RemoteException
{

System.out.println("Rejestracja klienta");
he = me;

background image

c

Karbowski, Kozakiewicz, Szynkiewiczowie, 2003

12

}

public void forget() throws java.rmi.RemoteException
{

System.out.println("Wyrejestrowanie klienta");
he = null;

}

public String say() throws java.rmi.RemoteException
{

try {

String text = he.what(); // Callback! To tak proste w RMI.

// Tak naprawdę he mogłoby

// być argumentem!

System.out.println(text);
return "Witaj! " + text;

}
catch (Exception e) {

System.out.println("Blad komunikacji:" + e.getMessage());

}
return null;

}

background image

c

Karbowski, Kozakiewicz, Szynkiewiczowie, 2003

13

}

class theClient implements Client {

Server textmaster;
String tekst;

theClient() throws java.rmi.RemoteException
{

tekst = null;
textmaster = null;
java.rmi.server.UnicastRemoteObject.exportObject(this);

}

public String what() throws java.rmi.RemoteException
{

System.out.println("-- Pytanie! Wysylam tekst...");
return tekst;

}

background image

c

Karbowski, Kozakiewicz, Szynkiewiczowie, 2003

14

public static void main(String args[])
{

try {

theClient me = new theClient();
me.tekst = "Test RMIkrofonu, 1, 2, 3...";
Factory dom = (Factory)java.rmi.Naming.lookup(

"//localhost/Fabryka");

System.out.println("Jest fabryka.");
me.textmaster = dom.get();
System.out.println("Jest serwer. Podanie referencji...");
me.textmaster.hello(me);
System.out.println("Praca...");
System.out.println( me.textmaster.say() );
System.out.println("Kasowanie referencji...");
me.textmaster.forget();
System.out.println("Koniec!");
me.textmaster = null;
me = null;
System.exit(0);

}

background image

c

Karbowski, Kozakiewicz, Szynkiewiczowie, 2003

15

catch (Exception e) {

// Nieładnie tak ogólnie, ale to tylko mały

// program. Tu może być java.rmi.RemoteException
// lub java.rmi.NotBoundException.

System.out.println("Niepowodzenie!: " + e.getMessage() );

}

}

}

background image

c

Karbowski, Kozakiewicz, Szynkiewiczowie, 2003

16

Wyniki

Kompilacja:

$ javac *.java
$ rmic theFactory theClient theServer

Serwer:

$ rmiregistry &
[1] 21708
$ java theFactory
Fabryka zarejestrowana
Nowy serwer!
Rejestracja klienta
Test RMIkrofonu, 1, 2, 3...
Wyrejestrowanie klienta

Klient:

$ java theClient
Jest fabryka.
Jest serwer. Podanie referencji...
Praca...
-- Pytanie! Wysylam tekst...
Witaj! Test RMIkrofonu, 1, 2, 3...

background image

c

Karbowski, Kozakiewicz, Szynkiewiczowie, 2003

17

Kasowanie referencji...
Koniec!

background image

c

Karbowski, Kozakiewicz, Szynkiewiczowie, 2003

18

Podsumowanie

RMI jest wyjątkowo udanym, choć nieco powolnym, narzędziem zdalnego wywoływania procedur. Jego
podstawową wadą jest przywiązanie do jednego języka (choć istnieje RMI over IIOP), w zamian jednak
integracja RMI w Javie jest wyjątkowo głęboka i cały mechanizm jest bardzo intuicyjny i wygodny.
Ewenementem jest użycie języka macierzystego do definicji interfejsu, jak również generowanie namiastek
i szkieletów z gotowych, skompilowanych klas. W praktyce RMI okazuje się jednym z najlepszych narzędzi
do szybkiego budowania prostych aplikacji rozproszonych.
Zastosowanie RMI w obliczeniach rozproszonych jest dość ograniczone, nie tyle nawet z powodu powolności
samego mechanizmu – jest wyraźnie wolniejszy od nieobiektowych, a nawet od CORBA – co z powodu
wad samego języka, który przystosowany jest raczej do innych celów.
Wywołania RMI są oczywiście blokujące, jak zwykle w RPC. W Javie wielowątkowość jest jednak
wbudowana w język, więc nie ma problemu z faktycznym zrównolegleniem obliczeń. Jedyną barierą
jest rozbudowana, obiektowa składnia, nie pasująca do większości matematycznych zastosowań, oraz
stosunkowo niska wydajność (choć nieporównanie lepsza, niż w początkach języka).


Wyszukiwarka

Podobne podstrony:
Resuscytacja dzieci i noworodków PRR zmiany wytycznych
kroplowy wlew dożylny, wytyczne 2010 - PRR, Rtwonictwo - egzamin praktyczny
RMI Dz-bud i tab-inf 020626, Budownictwo, Prawo
RMI (Dz U Nr0, poz 33)  07 2003 w sprawie szczegółowego zakresu i formy projektu budowlanego
RMI w sprawie dziennika budowy
RMI (Dz U Nr0, poz 26) # 06 2003 w sprawie informacji dotyczącej?zpieczeństwa i ochrony
PRR, Pierwsza pomoc
RMI w sprawie warunków technicznych, jakim powinny odpowiada
RMI z dnia 02 2003 w sprawie?zpieczeństwa i higieny pracy podczas wykonywania robót budowlanych
BLS dziecko, wytyczne 2010 - PRR, Rtwonictwo - egzamin praktyczny
wstrzyknięcie dożylne, wytyczne 2010 - PRR, Rtwonictwo - egzamin praktyczny
RMI Kompatyb el-magn030402, Budownictwo, Prawo
PRR ppt
odbarczenie odmy prężnej, wytyczne 2010 - PRR, Rtwonictwo - egzamin praktyczny
SRC-RMI 1
java rmi tutorial IL4RXEZIBFECTEJL7F2TXDTWIOWCBN3VN3U4BNQ
RMI z dnia0 sierpnia 04 r (Dz U Nr8, poz 43) w sprawie warunków i trybu postępowania w sprawach
czynności na?rmie ZiP grupa 3 i 4
RMI z dnia 7 kwietnia (Dz U Nr9 poz 1156) Zmieniające rozporządzenie w sprawie warunków technicznyc

więcej podobnych podstron