„Bună! Și încă un subiect fericit: RMI. RMI înseamnă Remote Method Invocation . Cu alte cuvinte, RMI este un mecanism care permite unui obiect dintr-o mașină Java să apeleze metode pe obiecte de pe o altă mașină Java , chiar dacă acestea sunt pe diferite mașini Java. computere, în diferite țări sau în diferite părți ale globului.”

RMI - 1

"Uau! Sună grozav."

"Da. Dar voi încerca doar să-ți dau o privire de ansamblu. Cu asta, dacă sapi prea adânc, poți fi confuz de nuanțele modului în care funcționează."

„Dar dacă nu mergi la extreme, atunci RMI nu este doar foarte simplu, dar simplifică și mult viața unui programator. Pentru care, îi aducem cele mai profunde respecturi.”

„Deci, vrem ca un obiect dintr-un program Java să apeleze o metodă pe un obiect care se află într-un alt program Java. Indiferent de unde rulează aceste programe.”

„Să luăm în considerare cel mai simplu exemplu: când ambele programe rulează pe același computer.  Pentru a permite programelor să interacționeze prin Internet, trebuie să configurați permisiunile JVM-ului , dar nu vom acoperi asta astăzi.”

„În Java, puteți apela de la distanță doar metodele interfețelor, nu clasele.”

"Așadar, avem două programe. Cum își pot numi metodele unul altuia?"

„Să luăm în considerare situația în care un program conține un obiect, iar un al doilea program dorește să apeleze metode pe acel obiect. Să numim primul program server, iar al doilea — clientul.

„Mai întâi, voi oferi niște exemplu de cod și apoi îl vom analiza.”

„Deci ce va face programul nostru?”

"Hmm. Ei bine, pentru simplitate, programul va avea o metodă care inversează un șir care îi este transmis."

— Destul de simplu.

„Bine, atunci să începem:”

„În primul rând, avem nevoie de o interfață care să ne satisfacă cerințele:”

Interfață de comunicare între programe
interface Reverse extends Remote
{
 public String reverse(String str) throws RemoteException;
}

„Am creat o interfață inversă și i-am adăugat o interfață de marcare la distanță, precum și o excepție la distanță. Pot apărea erori neașteptate atunci când metoda este apelată. Dacă o face, atunci această excepție va fi aruncată.”

„Acum trebuie să scriem o clasă de server care implementează această interfață:”

Clasa pentru server
class ReverseImpl implements Reverse
{
 public String reverse(String str) throws RemoteException
 {
  return new StringBuffer(str).reverse().toString();
 }
}

— Înțeleg. În această metodă inversăm șirul.

"Da."

"Acum trebuie să facem acest obiect apelabil dintr-un alt program. Iată cum faci asta:"

Partajarea obiectelor
public static final String UNIC_BINDING_NAME = "server.reverse";

public static void main(String[] args) throws Exception
{
 // Create an object to be accessible remotely.
 final ReverseImpl service = new ReverseImpl();

 // Create a registry of shared objects.
 final Registry registry = LocateRegistry.createRegistry(2099);
 // Create a stub for receiving remote calls.
 Remote stub = UnicastRemoteObject.exportObject(service, 0);
 // Register the stub in the registry.
 registry.bind(UNIC_BINDING_NAME, stub);

 // Put the main thread to sleep, or else the program will exit.
 Thread.sleep(Integer.MAX_VALUE);
}

„Voi explica această linie cu rând”.

În linia 1 , stocăm un nume unic (pe care l-am creat) pentru obiectul nostru la distanță (obiect care este accesibil de la distanță) în variabila UNIC_BINDING_NAME.  Dacă programul face mai multe obiecte accesibile, fiecare trebuie să aibă propriul nume unic. numele unic al obiectului este „server.reverse”.

" Pe linia 6 creăm un obiect ReverseImpl care va fi accesibil de la distanță. Metodele sale vor fi invocate."

" Pe linia 9 creăm un obiect special numit registry. Trebuie să-l folosim pentru a înregistra obiectele pe care le partajăm. JVM-ul va interacționa cu ele mai târziu. 2099 este un port (un număr unic pe care un alt program îl poate folosi pentru a accesa registru obiect)."

„Cu alte cuvinte, pentru a accesa un obiect, trebuie să cunoașteți numărul unic al registrului de obiecte (portul) și numele unic al obiectului și să aveți aceeași interfață ca cea implementată de obiectul la distanță.”

"Îmi dau seama. Ceva de genul: sunați prin telefon (aveți nevoie de un număr) și întrebați-l pe Bill (numele unui obiect)?"

— Da. Acum, să continuăm.

" Pe linia 11  , creăm un stub. Un stub este un obiect special care primește informații despre apelul de la distanță, îl despachetează, deserializează argumentele metodei și apelează metoda necesară. Apoi serializează rezultatul sau excepția, dacă a existat una , și trimite totul înapoi apelantului."

"Întâlnesc. Aproape. Ai spus că „deserializează argumentele metodei". Deci, asta înseamnă că argumentele metodelor de la distanță trebuie să fie serializabile?"

"Da. Cum altfel le-ai trimite prin rețea? Adevărat, există excepții, adică obiecte care sunt trecute prin referință, dar nu vom vorbi despre ele astăzi."

"O să o spunem așa: nu poți trece obiecte neserializabile, dar dacă vrei cu adevărat, atunci poți. Dar este o durere, știi."

"BINE."

— Atunci hai să continuăm.

La linia 13 , înregistrăm stub-ul obiectului nostru sub un nume unic în registru.”

" Pe linia 16 , punem firul principal în repaus. Toate apelurile la distanță sunt procesate pe fire separate. Important este că programul rulează. Așa că pur și simplu punem firul principal în repaus aici. Asta este."

"BINE."

„Bine, atunci iată un exemplu de client:”

Lucrul cu un obiect la distanță
public static final String UNIC_BINDING_NAME = "server.reverse";

public static void main(String[] args) throws Exception
{
 // Create a registry of shared objects
 final Registry registry = LocateRegistry.createRegistry(2099);

 // Get the object (actually, this is a proxy object)
 Reverse service = (Reverse) registry.lookup(UNIC_BINDING_NAME);

 // Call the remote method
 String result = service.reverse("Home sweet home.");
}

„Voi explica acest cod linie cu linie:”

" Linia 1 este numele unic  al obiectului la distanță . Acesta trebuie să fie același atât pe client, cât și pe server."

În linia 6  , creăm un „ registru de obiecte la distanță ”. Portul său (2099) trebuie să fie același cu portul registrului pentru aplicația server.”

" Pe linia 9 , obținem obiectul din registry. Obiectul returnat este un obiect proxy și este convertit într-o interfață. Interfața trebuie să moștenească interfața de marcare la distanță."

Pe linia 12 , numim metodele interfeței ca și cum obiectul ar fi fost creat în cadrul aceluiași program. Nu există nicio diferență.”

"Cool! Acum pot scrie aplicații distribuite. Sau jocuri precum Battleship pentru Android."

„Nu îndrăzni, Amigo! Sistemul de operare Android a fost interzis în secolul al 27-lea după a treia încercare de a cuceri lumea. Roboții nu au acces la el. Nu ar exista nicio modalitate de a te îndepărta de el. . Începeai să alergi în jur strigând: «Ucide toți oamenii!»”

"Hmm. OK. Dar tot va trebui să-l întreb pe Diego. Nu se știe niciodată, poate că va avea ceva interesant de spus despre asta."

"Atunci du-te și întreabă-l. Bine, ei bine, până mâine."

"La revedere, Rishi. Mulțumesc pentru lecția interesantă."