close

Java Remote Method Invocation

Ga naar navigatie Ga naar zoeken

RMI ( Java Remote Method Invocation ) is een door Java aangeboden mechanisme om een ​​methode op afstand aan te roepen . Het maakt deel uit van de standaard Java runtime-omgeving en biedt een eenvoudig mechanisme voor servercommunicatie in gedistribueerde Java-only applicaties. Als communicatie tussen andere technologieën vereist is, moet CORBA of SOAP worden gebruikt in plaats van RMI.

RMI wordt gekenmerkt door zijn gebruiksgemak bij het programmeren, omdat het specifiek is ontworpen voor Java; biedt objectpassage door verwijzing (niet toegestaan ​​door SOAP), gedistribueerde garbagecollection (Distributed Garbage Collector) en willekeurig doorgeven van type (functionaliteit niet geleverd door CORBA).

Via RMI kan een Java-programma een object exporteren , waardoor het object toegankelijk wordt via het netwerk en het programma wacht op verzoeken op een TCP-poort . Daarna kan een client verbinding maken en de methoden aanroepen die door het object worden geboden.

De aanroep bestaat uit de volgende stappen:

  • Het rangschikken van parameters (met behulp van de serialisatiefunctionaliteit van Java ).
  • Aanroep van de methode (van de client op de server). De beller wacht op een antwoord.
  • Nadat de uitvoering is voltooid, serialiseert de server de retourwaarde (indien aanwezig) en stuurt deze naar de client.
  • De clientcode ontvangt het antwoord en gaat verder alsof de aanroep lokaal was.

Context

Sinds JDK versie 1.1 heeft Java zijn eigen ORB : RMI (Remote Method Invocation). Hoewel RMI in algemene zin een ORB is, is het geen CORBA-compatibel model. RMI is inheems in Java, dat wil zeggen, het is een uitbreiding op de kerntaal. RMI vertrouwt volledig op de kern van Java Object Serialization, evenals de implementatie van zowel portabiliteit als mechanismen voor het laden en lossen van objecten op andere systemen, enz.

Het gebruik van RMI is heel natuurlijk voor elke Java-programmeur, omdat hij geen nieuwe technologie hoeft te leren die totaal verschilt van degene waarmee hij zich zal ontwikkelen. RMI heeft echter enkele beperkingen vanwege de nauwe integratie met Java, waarvan de belangrijkste is dat deze technologie geen interactie toestaat met applicaties die in een andere taal zijn geschreven.

RMI, als een uitbreiding van Java, is een programmeertechnologie die is ontworpen om problemen op te lossen door uitvoerbare code te schrijven en te organiseren. Zo vormt RMI een specifiek punt in de ruimte van programmeertechnologieën samen met C, C++, Smalltalk, enz.

Het belangrijkste verschil tussen het gebruik van RPC en RMI is dat RMI een mechanisme is voor het op afstand aanroepen van procedures op basis van de Java-programmeertaal die interactie tussen objecten ondersteunt, terwijl RPC deze functie niet ondersteunt.

Architectuur

De RMI-architectuur kan worden gezien als een model met vier lagen.

Eerste laag

De eerste laag is de applicatielaag en komt overeen met de daadwerkelijke implementatie van de client- en serverapplicaties. Hier vinden oproepen op hoog niveau plaats voor toegang tot en export van externe objecten. Elke toepassing die wil dat zijn methoden beschikbaar zijn voor toegang door externe clients, moet die methoden declareren in een interface die java.rmi.Remote uitbreidt. Zo'n interface wordt in principe gebruikt om een ​​object te "markeren" als op afstand toegankelijk. Nadat de methoden zijn geïmplementeerd, moet het object worden geëxporteerd. Dit kan impliciet worden gedaan als het object de klasse UnicastRemoteObject (pakket java.rmi.server) uitbreidt, of het kan expliciet worden gedaan door de methode exportObject() van hetzelfde pakket aan te roepen.

Tweede laag

Laag 2 is de proxy-laag of stub-skeletlaag. Deze laag is degene die direct in wisselwerking staat met de applicatielaag. Alle aanroepen naar externe objecten en acties samen met hun parameters en retourobjecten vinden plaats in deze laag.

Derde laag

Laag 3 is de externe referentielaag en is verantwoordelijk voor het afhandelen van het semantische deel van externe aanroepingen. Het is ook verantwoordelijk voor het beheer van objectreplicatie en het uitvoeren van implementatiespecifieke taken met externe objecten, zoals het vaststellen van semantische persistentie en juiste strategieën voor het herstellen van verloren verbindingen. In deze laag wordt vanuit de transportlaag een stroomgerichte verbinding verwacht.

Vierde laag

Laag 4 is de transportlaag. Het is verantwoordelijk voor het maken van de nodige verbindingen en het beheren van het transport van gegevens van de ene machine naar de andere. Het onderliggende transportprotocol voor RMI is Java Remote Method Protocol (JRMP), dat alleen door Java-programma's wordt "begrepen".

Elementen

Elke KMI-aanvraag valt normaal gesproken uiteen in 2 delen:

  • Een server, die enkele objecten op afstand aanmaakt, maakt referenties om ze toegankelijk te maken en wacht tot de client ze aanroept.
  • Een client die een verwijzing naar externe objecten op de server verkrijgt en deze aanroept.

Voorbeeld

Een RMI-server bestaat uit het definiëren van een object op afstand dat door clients zal worden gebruikt. Om een ​​object op afstand te maken, wordt een interface gedefinieerd en het object op afstand zal een klasse zijn die die interface implementeert. Laten we eens kijken hoe we in 3 stappen een voorbeeldserver kunnen maken:

  • Definieer de externe interface. Wanneer een externe interface wordt gemaakt:
    • De interface moet openbaar zijn.
    • Het moet erven van de java.rmi.Remote-interface, om aan te geven dat het kan worden aangeroepen vanaf elke virtuele Java-machine.
    • Elke methode op afstand moet de uitzondering java.rmi.RemoteException in zijn throws-clausule gooien, naast alle uitzonderingen die hij aankan.
openbare  interface  MyRemoteInterface  breidt  java uit . rmi . Remote 
{ 
  public  void  myMethod1 ()  gooit  java . rmi . Uitzondering op afstand ; 
  public  int  myMethod2 ()  gooit  java . rmi . Uitzondering op afstand ; 
}
  • Implementeer de externe interface
public  class  MyRemoteClass  
 breidt  java uit . rmi . server . UnicastRemoteObject  
 implementeert  MyRemoteInterface 
{ 
 public  MyRemoteClass ()  gooit  java . rmi . RemoteException 
 { 
   super ();  //Bel de constructor van de basisklasse (UnicastRemoteObject) 
   // Constructorcode 
 }
 
 public  void  myMethod1 ()  gooit  java . rmi . RemoteException 
 { 
   // Hier plaatsen we de code die we willen 
   System . uit . println ( "Ik ben in mijnMethod1()" ); 
 }

 public  int  myMethod2 ()  gooit  java . rmi . RemoteException 
 { 
   return  5 ;  // Hier plaatsen we de code die we willen 
 }

 public  void  otherMethod () 
 { 
   // Als we een andere methode definiëren, kan deze niet worden aangeroepen 
   // op afstand omdat deze niet afkomstig is van de externe interface 
 }
 
 public  static  void  main ( String []  args ) 
 { 
   probeer 
   { 
     MyRemoteInterface  mir  =  nieuwe  MyRemoteClass (); 
     java . rmi . Benoemen . rebind ( "rmi://"  +  java .net . InetAddress . getLocalHost ( ) . getHostAddress ( ) + ":" + args [ 0 ] + "/TestRMI" , mir ); } catch ( Uitzondering e ) { e . printStackTrace (); } } } 
                                  
   
     
   
     
   
 

  • Zoals u kunt zien, implementeert de klasse MyRemoteClass de MyRemoteInterface-interface die we eerder hebben gedefinieerd. Het erft ook van UnicastRemoteObject, een Java-klasse die we kunnen gebruiken als een superklasse om objecten op afstand te implementeren.
  • Vervolgens definiëren we binnen de klasse een constructor (die de RemoteException-uitzondering genereert omdat deze ook wordt gegenereerd door de UnicastRemoteObject-superklasse), en de methoden van de interface(s) die deze implementeert.
  • Ten slotte definiëren we in de main-methode de code om het externe object te maken dat we willen delen en om het externe object zichtbaar te maken voor clients, met behulp van de Naming-klasse en zijn rebind(...)-methode.

Opmerking: voor het gemak hebben we de methode main() in dezelfde klasse geplaatst. Er kan een aparte klasse worden gedefinieerd die verantwoordelijk is voor het registreren van het externe object.

  • De server compileren en uitvoeren

We hebben de server al gedefinieerd. Nu moeten we je klassen samenstellen met behulp van de volgende stappen:

    • We compileren de externe interface. Daarnaast groeperen we het in een JAR-bestand om het zowel op de client als op de server aanwezig te houden:
javac MyRemoteInterface.java
jar cvf objRemotes.jar MyRemoteInterface.class
    • Vervolgens compileren we de klassen die de interfaces implementeren. En voor elk van hen genereren we de Stub- en Skeleton-bestanden om de verwijzing naar het externe object te behouden, met behulp van het rmic-commando:
set CLASSPATH=%CLASSPATH%;.\Remoteobj.jar;.
javac MyRemoteClass.java
rmic -d . MijnRemoteClass

We kunnen in onze werkdirectory zien dat er automatisch twee .class-bestanden zijn gegenereerd (MiClaseRemota_Skel.class en MiClaseRemota_Stub.class) die overeenkomen met de stub-skeletlaag van de RMI-architectuur.

  • Om de server te laten draaien, volgen we deze stappen:
    • RMI-loggen wordt gestart om loggen en zoeken van objecten op afstand mogelijk te maken. Het register is verantwoordelijk voor het beheren van een set objecten op afstand die moeten worden gedeeld, en voor het zoeken naar deze objecten op verzoek van klanten. Het werkt met de rmiregistry-toepassing die wordt gedistribueerd met Java, waaraan we optioneel de poort kunnen doorgeven om verbinding mee te maken (standaard 1099).

In het geval van Windows moet het worden uitgevoerd:

start rmiregistry 1234

En in het geval van Linux:

rmiregister &
    • Ten slotte wordt de server gelanceerd:
java -Djava.rmi.server.hostname=127.0.0.1 MyRemoteClass 1234
  • Een RMI-client maken

We gaan nu een client definiëren die toegang heeft tot de externe objecten die we maken. Hiervoor volgen we de volgende stappen:

    • Definieer de klasse om de vereiste externe objecten te krijgen

De volgende klasse krijgt een object van het type MyRemoteInterface, geïmplementeerd op onze server:

openbare  klas  MyRMICclient 
{

 privé  MijnRMICclient (){}; 

 public  static  void  main ( String []  args ) 
 { 
   probeer 
   { 
     MyRemoteInterface  mir  =  ( MyRemoteInterface ) java . rmi . Benoemen . lookup ( "rmi://"  +  
                             args [ 0 ]  +  ":"  +  args [ 1 ]  +  "/RMITest" );
     
     // Print myMethod1() zo vaak als myMethod2() retourneert 
     voor  ( int  i = 1 ; i <= myr . myMethod2 (); i ++ )  
         myr . mijnMethode1 (); 
   } 
   catch  ( Uitzondering  e ) 
   { 
     e . printStackTrace (); 
   } 
 } 
}

Zoals u kunt zien, bestaat het eenvoudigweg uit het zoeken naar het externe object in het RMI-register van de externe machine. Om dit te doen gebruiken we de klasse Naming en de bijbehorende lookup(...)-methode.

    • De client compileren en uitvoeren

Zodra we de client al hebben gedefinieerd, doen we om deze te compileren:

set CLASSPATH=%CLASSPATH%;.\Remoteobj.jar;.
javac MijnRMICclient.java

Om de client vervolgens uit te voeren, doen we:

java MyClientRMI 127.0.0.1 1234

Het stub-bestand van de externe klasse moet toegankelijk zijn. Om dit te doen, kopiëren we het naar de client en nemen het op in het CLASSPATH, of verwijderen het uit het CLASSPATH van de server en nemen het pad op in de java.rmi.codebase van de server (indien niet verwijderd uit het CLASSPATH van de server, de optie java. rmi.codebase, en de client heeft geen toegang tot de Stub. Als we kijken naar het venster waarin de RMI-server draait, zullen we zien hoe het externe object is gevonden en hoe de methoden zijn uitgevoerd:

Zie ook

Externe links