L'implementazione dell'RMI

L'implementazione RMI è composta da tre livelli di astrazione.

Questi livelli di astrazione sono:
  1. Il livello Stub e Skeleton , che intercetta chiamate di metodo effettuate dal client alla variabile di riferimento dell'interfaccia e reindirizza tali chiamate a un servizio RMI remoto.
  2. Il livello Riferimento remoto comprende come interpretare e gestire i riferimenti effettuati dai client agli oggetti servizio remoti.
  3. Il livello inferiore è il livello Trasporto , basato sulle connessioni TCP/IP tra le macchine in una rete. Fornisce connettività di base, così come alcune strategie di penetrazione del firewall.
Questo diagramma mostra la relazione tra programma client e programma server tramite il sistema RMI. Il sistema RMI comprende gli stub e le strutture e il livello di riferimento remoto sia sul lato client che sul lato server, collegati dal livello di trasporto.

Oltre al livello TCP/IP, RMI utilizza un protocollo a livello di collegamento denominato JRMP (Java™ Remote Method Protocol), che funziona come segue:

  1. Gli oggetti che richiedono un funzionamento remoto devono estendere la classe RemoteObject , generalmente attraverso la sottoclasse UnicastRemoteObject .
    1. La sottoclasse UnicastRemoteObject esporta l'oggetto remoto per renderlo disponibile per le chiamate RMI in arrivo.
    2. L'esportazione dell'oggetto remoto crea un nuovo socket server, collegato a un numero di porta.
    3. Viene creato anche un thread che è in ascolto per le connessioni su tale socket. Il server è registrato con un registro.
    4. Un client ottiene i dettagli di connessione al server dal registro.
    5. Utilizzando le informazioni del registro, che includono il nome host e i dettagli della porta del socket di ascolto del server, il client si collega al server.
  2. Quando il client emette un richiamo del metodo remoto al server, crea un oggetto TCPConnection , che apre un socket al server sulla porta specificata e invia le informazioni sull'intestazione RMI e gli argomenti di marshalling tramite questa connessione utilizzando la classe StreamRemoteCall .
  3. Sul lato server:
    1. Quando un client si collega al socket del server, viene assegnato un nuovo thread per gestire la chiamata in ingresso. Il thread originale può continuare ad ascoltare il socket originale in modo da poter effettuare ulteriori chiamate da parte di altri client.
    2. Il server legge le informazioni sull'intestazione e crea un oggetto RemoteCall per gestire l'annullamento del marshalling degli argomenti RMI dal socket.
    3. Il metodo serviceCall() della classe Transport esegue la chiamata in entrata inviandola
    4. Il metodo dispatch() richiama il metodo appropriato sull'oggetto e spinge il risultato verso il basso.
    5. Se l'oggetto server genera un'eccezione, il server la rileva e la esegue il marshalling del collegamento invece del valore di ritorno.
  4. Di nuovo sul lato client:
    1. Il valore di ritorno dell'RMI viene annullato e restituito dallo stub al codice client stesso.
    2. Se viene generata un'eccezione dal server, viene eseguito l'unmarshalling e viene generato dallo stub.