Title: Remote Method Invocation
1Remote Method Invocation
Perché RMI? Lobiettivo è di permettere ad una
applicazione in esecuzione su una macchina locale
di invocare i metodi di un oggetto in esecuzione
su un altro computer remoto. Si colloca quindi
del mondo della programmazione distribuita. Si
definisce client il programma chiamante che
ottiene riferimento alloggetto remoto, server il
programma che crea gli oggetti remoti. Tali
applicazioni sono anche denominate distributed
object application
Nicola Gessa
2Quali vantaggi?
- miglioramento delle prestazione complessive
- semplicità nella gestione delle risorse
distribuite - incremento della potenza operativa
- es suddivisione di una computazione pesante in
sottoroutine più piccole, eseguite tutte su
macchine diverse diminuendo in tal modo il tempo
complessivo di esecuzione
3Sistema distribuito.
- . quindi si deve disporre di un meccanismo di
comunicazione - Java implementa il meccanismo dei socket in
maniera semplice e risolve il problema di come
instaurare la connessione ma coi socket... - non definisce le modalità di invocazione di
metodi - non definisce protocolli per lo scambio di
informazioni
4Caratteristiche di RMI
- Utilizzando la libreria RMI di Java è possibile
per un oggetto in esecuzione su una JVM di
richiedere lesecuzione di un metodo di un
oggetto in esecuzione su unaltra JVM - RMI richiede lutilizzo esclusivo di Java come
linguaggio di sviluppo -gt difficile integrazione
con altri linguaggi - semplicità e velocità nello sviluppo
- meno potenzialità e scalabilità
- Dynamic Code Loadingpossibilità di scaricare il
bytecode di una classe se la classe non è
definita nella virtual machine del ricevente,
mantenendo la definizione dei tipi e il loro
comportamento. In questo modo una applicazione
può estendere le sue funzionalità ricevendo delle
nuove classi da utilizzare durante lesecuzione.
5La serializzazione
- Il meccanismo alla base utilizzato da RMI per la
trasmissione dei dati fra client e server è
quello della serializzazione che permette il
flusso di dati complessi allinterno di stream
(può venir usata indipendentemente da
applicazioni RMI) - La serializzazione consiste nella trasformazione
automatica di oggetti e strutture in sequenze di
byte manipolabili coi vari stream del package
java.io - Gli stream sono associabili sia a socket che a
file - es
- Record record new Record()
- ObjectOutputStream oos new ObjectOutputStream(my
os) - oos.writeObject(record)
6La serializzazione
- Un oggetto è serializzabile se implementa
linterfaccia Serializable - Si possono serializzare oggetti con struttura e
complessità arbitraria, senza particolari
differenze, a patto che loggetto si
serializzabile (implementi linterfaccia
Serializable) - es
- public class Record implements Serializable
- private String Nome
- public Record(String Nome)
- this.Nome Nome
-
-
7La serializzazione
- La serializzazione è ricorsiva ( un oggetto
serializzabile deve contenere oggetti
serializzabili) - La maggior parte delle classi del JDK è
serializzabile (eccetto alcune che adottano
strutture dati binarie dipendenti dall
piattaforma)
8Architetture di RMI
La struttura di unapplicazione RMI è organizzata
in strati orizzontali sovrapposti
RMI Client
RMI Server
Java Virtual Machine
Oggetto reale eseguito sul server
Simuazione locale sul client
Stubs
Skeleton
Remote Reference Layer
Remote Reference Layer
Connessione virtuale
Transport Layer
Transport Layer
Connessione fisica
9Architetture di RMI
- Lo strato più alto è costituito da applicazioni
(client e server) eseguite dalla Java Virtual
Machine - Lo stub e lo skeleton forniscono la
rappresentazione delloggetto remoto lo stub
gestisce la simulazione locale sul client e
agendo come proxy consente la comunicazione con
loggetto remoto, lo skeleton ne consente
lesecuzione sul server - Il client esegue i metodi delloggetto remoto in
modo del tutto analogo alla chiamata locale - ris OggettoRemoto.nomeMetodo(par1, par2,..)
- senza preoccuparsi dei dettagli della
comunicazione - Il client ha solo in minima parte la sensazione
di usare un oggetto remoto
10Passaggio di parametri
- Percorso dei parametri
- Serializzati dalla Virtual Machine
- Inviati sotto forma di stream al server
- Deserializzati del server che li utilizza
allinterno del corpo del metodo invocato - Il risultato segue il percorso inverso fino ad
arrivare al client
11Gli strati RRL e TL
Si occupano della gestione a basso livello (
allinterno dellarchitettura RMI) della
comunicazione
- Il Remote Reference Layer (RRL) ha il compito di
instaurare un connessione virtuale fra il client
e il server ( esegue operazioni di codifica e
decodifica dei dati). Questo adotta un protocollo
generico e indipendente dal tipo di stub o
skeleton utilizzato - Il Transport Layer esegue la connessione vera e
propria tra le macchine utilizzando le specifiche
standard di networking di Java, e quindi i socket
con il protocollo TCP/IP
12Il Transport Layer
- Il TL è responsabile del controllo dello stato
delle vari connessioni - I dati vengono visti come sequenze di byte da
inviare o da leggere - IL TL si incarica di localizzare il server RMI
relativo alloggetto remoto richiesto - Esegue la connessione per mezzo di un socket
13Security manager
- La possibilità di scaricare codice è controllata
e regolata da un security manager che opera in
accordo ad una policy - Il client e il server devono essere eseguiti con
una policy adeguata alle loro esigenze e alle
esigenze di sicurezza del sistema specificando il
parametro - Djava.security.policyjava.policy
- al momento del lancio dellesecuzione.
Java.policy è il nome del file dove viene
specificata la politica di sicurezza.
14I file java.policy
- Esempi di tali file possono essere
grant permission java.security.AllPermis
sion
grant permission java.net.SocketPermission
1024-65535, connect,accept permission
java.net.SocketPermission 80, connect
15Programmare con RMI
- Le classi e i metodi sono contenuti nei package
java.rmi e java.rmi.server - Si definisce oggetto remoto un oggetto che
implementi linterfaccia Remote i cui metodi
possono essere eseguiti da unapplicazione client
posta su unaltra macchina virtuale - Un oggetto diventa remoto se implementa
uninterfaccia remota, ossia uninterfaccia che
estende linterfaccia java.rmi.Remote
16Le classi di oggetti remoti
- Una classe può implementare un numero a piacere
di interfacce remote. - Una classe può estendere una classe che
implementa una interfaccia remota. - Una classe può definire anche dei metodi che non
fanno parte delle interfacce remote e che
pertanto sono chiamabili solo in locale - La classe deve supportare accessi concorrenti
perché più client potrebbero usarla
contemporaneamente. (Bisogna usare metodi/blocchi
synchronized dove serve)
17Client e server in RMI?
- Sia il client che il server di una
applicazione possono allocare degli oggetti
remoti ed esportarli con un nome sul registry
oppure possono passarli come parametri di altri
oggetti remoti. - Dal punto di vista del singolo oggetto remoto il
server è chi lo alloca e lo esporta mentre il
client è chi richiede un riferimento ad un
oggetto remoto. - In definitiva quindi con RMI tutte le parti di
una applicazione distribuita possono agire sia
come client che come server.
18Come trasformare un oggetto in un oggetto remoto?
Oggetto classico
public class MyServer public String
concat(String a, String b) return ab
Corrispettiva implementazione remota
public interface MyServerInterface extend
Remote public String concat (String a, String
b)throws RemoteException
public class MyServerImpl implements
MyServerInterface extends UnicastRemoteObject
public MyServerImpl() throws RemoteException
public String concat (String a, String
b)throws RemoteException return ab
19Hello World con RMI
- Scrivere lintefaccia delloggetto remoto
Hello.java - Scrivere il client che richiede laccesso
alloggetto remoto HelloClient.java - Scrivere il server che implementa linterfaccia e
la rende accessibile HelloImpl.java da cui in
seguito generare stub e skeleton
20Hello World con RMI - linterfaccia
- Linterfaccia remota deve dichiarare tutti i
metodi che si vuole poter richiamare in maniera
remota - deve essere dichiarata public
- deve estendere linterfaccia java.rmi.Remote
- ogni metodo deve dichiarare java.rmi.RemoteExcept
ion nella sezione throws per proteggere
lapplicazione da anomalie derivanti
dallutilizzo di risorse remote
//linterfaccia delloggetto remoto package
hello import java.rmi.Remote import
java.rmi.RemoteException public interface Hello
extends Remote String sayHello() throws
RemoteException
21Implementazione delloggetto remoto
- deve implementare almeno uninterfaccia remota
- deve definire i costruttori delloggetto remoto
- deve fornire limplementazione dei metodi
invocati da remoto - creare e installare il security manager
- creare una o più istanza delloggetto
- identificare e registrare listanza delloggetto
con un nome nel rmiregistry
22Implementare linterfaccia remota
public class HelloImpl extends UnicastRemoteObject
implements Hello
- dichiara che implementa lintefaccia Hello ( con
tutti i sui metodi) - estende la classe UnicastRemoteObject per
consentire la creazione di un oggetto remoto che - adotta i protocolli di comunicazione di default
di RMI basata sui socket e TCP - rimane costantemente attivo
23Definire i costruttori
public HelloImpl()throws RemoteException super(
)
- il metodo super() chiama il costruttore della
classe UnicastRemoteObject che esegue le
inizializzazioni necessarie per consentire di
rimanere in attesa (listen) di richieste remote
su una porta e poterle gestire (accept) - potrebbe generare leccezione RemoteException se
la connessione non fosse possibile
24Implementazione dei metodi remoti
public String sayHello() return "Hello
World"
- devono essere implementati tutti i metodi
dellinterfaccia - gli argomenti dei metodi e i risultati restituiti
devono essere oggetti serializzabili
25Il security manager
Chi garantisce che il codice scaricato da remoto
non esegua operazioni pericolose?
if(System.getSecurityManager()
null) System.setSecurityManager(new
RMISecurityManager())
- Il metodo main deve creare e installare un
security manager, che può essere il
RMISecurityManager o definito in altro modo - Il S.M. garantisce che le classi che vengono
caricate non eseguano operazioni per le quali non
siano abilitate - se il S.M non è specificato non è permesso nessun
caricamento di classi da parte sia del client (
stub ) che del server
26Istanziare gli oggetti remoti
HelloImpl obj new HelloImpl()
- Nel metodo main si devono creare una o più
istanze delloggetto che fornisce il servizio - Una volta creato, loggetto è pronto per
accettare richieste remote
27Registrare loggetto remoto
- Naming.rebind("//localhost/HelloServer",obj)
- Il client deve poter ottenere un riferimento
alloggetto remoto - RMI fornisce un registry degli oggetti per creare
unassociazione (bind) fra un nome URL-formatted
e un oggetto - lRMI registry è un name-service che consente ai
client di ottenere riferimenti agli oggetti una
volta registrato loggetto i client possono farne
richiesta attraverso il nome e invocarne i metodi - nessun protocollo deve essere specificato nel
primo argomento - la porta di default su cui risponde il
RMIregistry è la 1099, ma può essere cambiata
28Registrare loggetto remoto
- Un applicazione puo creare unassociazione solo
sul RMIregistry del host locale - I client possono invece eseguire la propria
ricerca di oggetti su qualunque host - Loperazione di registrazione può generare varie
eccezioni - AlreadyBoundException, se il nome logico è gia
utilizzato - MalformedURLException, per errori nella sintassi
dellURL - RemoteException negli altri casi
29// implementazione delloggetto remoto package
hello import java.rmi.RemoteException import
java.rmi.Naming import java.rmi.server.UnicastRem
oteObject import java.rmi.RMISecurityManager pu
blic class HelloImpl extends UnicastRemoteObject
implements Hello public HelloImpl()throws
RemoteException super() public String
sayHello() return "Hello World" public
static void main(String args) if(System.getSe
curityManager() null) System.setSecurityMan
ager(new RMISecurityManager()) try
HelloImpl obj new HelloImpl() Naming.re
bind("//localhost/HelloServer",obj) System.out
.println("Hello Server bound in
registry") catch(Exception e) System.out.p
rintln("HelloImpl err "e.getMessage())
30Un client per richiamare gli oggetti remoti
- Deve ottenere un riferimento alloggetto remoto
che vuole richiamare dal RMIregistry eseguito sul
server, utilizzando unistanza dello stub a cui
passare hostname ( ed eventualmente porta) e nome
delloggetto - obj (Hello)Naming.lookup("//localhost/HelloServer
") - Richiama i metodi delloggetto secondo la
sintassi solita - message obj.sayHello()
31// il client per richiamare loggetto remoto
Hello import java.rmi.Naming import
java.rmi.RemoteException import
java.rmi.RMISecurityManager public class
HelloClient public static void main(String
args)
String message"" Hello objnull
if (System.getSecurityManager()
null)
System.setSecurityManager(new RMISecurit
yManager())
try
obj (Hello)Naming.lookup(
"//localhost/HelloServer")
message obj.sayHello()
System.out.println(message)
catch (Exception e)
System.err.println("Hello Server exception "
e.getMessage())
e.printStackTrace()
32Compilazione ed esecuzione
- Compilare i file .java col javac per creare i
file .class - Generare stub e skeleton col comando rmic sul
file che contiene limplementazione delloggetto
remoto (HelloImpl.class) - rmic hello.HelloImpl
- questo genera i file HelloImpl_Stub.class e
HelloImpl_Skel.class - Lanciare in background sul server lRMIregistry
col comando rmiregistry . Questo utilizza per
default la porta 1099 per utilizzarne unaltra
specificarla come parametro (es. rmiregistry 2001
). Ogni volta che viene modificata
uninterfaccia remota deve essere rieseguito - Lanciare il server
- Lanciare il client
33Compilazione ed esecuzione
javac hello\Hello.java javac HelloClient.java java
c hello\HelloImpl.java rmic hello.HelloImpl rmir
egistry java -Djava.security.policyjava.policy
hello.HelloImpl java -Djava.security.policyjav
a.policy HelloClient localhost
- Compilare i file .java col javac per creare i
file .class - Generare stub e skeleton col comando rmic sul
file che contiene limplementazione delloggetto
remoto (HelloImpl.class) - rmic hello.HelloImpl
- questo genera i file HelloImpl_Stub.class e
HelloImpl_Skel.class - Lanciare in background sul server lRMIregistry
col comando rmiregistry . Questo utilizza per
default la porta 1099 per utilizzarne unaltra
specificarla come parametro (es. rmiregistry 2001
). Ogni volta che viene modificata
uninterfaccia remota deve essere rieseguito - Lanciare il server
- Lanciare il client
34Esempio sulla concorrenzaloggetto remoto
- Creiamo uninterfaccia remota che consenta di
incrementare un valore è proviamo a chiamarla da
client diversi. Cosa succede? Se vogliamo
proteggere parti di codice dei metodi degli
oggetti remoti da accessi concorrenti pericolosi
dobbiamo definire questo codice allinterno di
blocchi synchronized
35Esempio sulla concorrenzaloggetto remoto
package ValNumero import java.rmi.Remote impor
t java.rmi.RemoteException public interface
newValNumero extends Remote int getValore()
throws RemoteException int setValore(int i)
throws RemoteException int incValore() throws
RemoteException
Implementazione del metodo che incrementa il
valore
synchronized public int incValore() int
j //val funziona senza gestire la
concorrenza con synchronozed! jthis.getValore()
this.setValore(j1) return 1