"Hallo! Und noch ein erfreuliches Thema: RMI. RMI steht für Remote Method Invocation . Mit anderen Worten, RMI ist ein Mechanismus, der es einem Objekt von einer Java-Maschine ermöglicht, Methoden für Objekte von einer anderen Java-Maschine aufzurufen , selbst wenn diese sich auf einer anderen befinden Computer, in verschiedenen Ländern oder auf verschiedenen Seiten der Welt.

RMI - 1

„Whoa! Das hört sich großartig an.“

„Ja. Aber ich versuche nur, Ihnen einen Überblick zu geben. Wenn Sie dabei zu tief graben, können Sie von den Nuancen der Funktionsweise verwirrt werden.“

„Aber wenn man nicht ins Extreme geht, dann ist RMI nicht nur sehr einfach, sondern es vereinfacht auch das Leben eines Programmierers enorm. Dafür zollen wir ihm unseren tiefsten Respekt.“

„Wir möchten also, dass ein Objekt in einem Java-Programm eine Methode für ein Objekt aufruft, das sich in einem anderen Java-Programm befindet. Unabhängig davon, wo diese Programme ausgeführt werden.“

„Betrachten wir das einfachste Beispiel: Wenn beide Programme auf demselben Computer laufen.  Damit Programme über das Internet interagieren können, müssen Sie die Berechtigungen der JVM konfigurieren , aber darauf gehen wir heute nicht ein.“

„In Java können Sie aus der Ferne nur die Methoden von Schnittstellen aufrufen, keine Klassen.“

„Wir haben also zwei Programme. Wie können sie die Methoden des anderen aufrufen?“

„Betrachten wir die Situation , in der ein Programm ein Objekt enthält und ein zweites Programm Methoden für dieses Objekt aufrufen möchte. Nennen wir das erste Programm den Server und das zweite den Client.

„Zuerst stelle ich Beispielcode zur Verfügung, und dann analysieren wir ihn.“

„Was wird unser Programm also bewirken?“

„Hmm. Nun, der Einfachheit halber verfügt das Programm über eine Methode, die eine ihm übergebene Zeichenfolge umkehrt.“

"Einfach genug."

„Gut, dann fangen wir an:“

„Zuerst brauchen wir eine Schnittstelle, die unseren Anforderungen gerecht wird:“

Schnittstelle zur Kommunikation zwischen Programmen
interface Reverse extends Remote
{
 public String reverse(String str) throws RemoteException;
}

„Ich habe eine Reverse-Schnittstelle erstellt und ihr eine Remote-Marker-Schnittstelle sowie eine RemoteException hinzugefügt. Beim Aufruf der Methode können unerwartete Fehler auftreten. Wenn dies der Fall ist, wird diese Ausnahme ausgelöst.“

„Jetzt müssen wir eine Serverklasse schreiben, die diese Schnittstelle implementiert:“

Klasse für den Server
class ReverseImpl implements Reverse
{
 public String reverse(String str) throws RemoteException
 {
  return new StringBuffer(str).reverse().toString();
 }
}

„Ich verstehe. Bei dieser Methode kehren wir die Zeichenfolge um.“

"Ja."

„Jetzt müssen wir dieses Objekt von einem anderen Programm aus aufrufbar machen. So machen Sie das:“

Objektfreigabe
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);
}

„Ich werde das Zeile für Zeile erklären.“

" In Zeile 1 speichern wir einen eindeutigen Namen (den wir uns ausgedacht haben) für unser Remote-Objekt (Objekt, auf das aus der Ferne zugegriffen werden kann) in der Variable  UNIC_BINDING_NAME . Wenn das Programm mehrere Objekte zugänglich macht, muss jedes seinen eigenen eindeutigen Namen haben. Das unser Der eindeutige Name des Objekts lautet „server.reverse“.

In Zeile 6 erstellen wir ein ReverseImpl- Objekt, auf das remote zugegriffen werden kann. Seine Methoden werden aufgerufen.“

In Zeile 9 erstellen wir ein spezielles Objekt namens Registry. Wir müssen es verwenden, um die Objekte zu registrieren, die wir teilen. Die JVM wird später mit ihnen interagieren. 2099 ist ein Port (eine eindeutige Nummer, die ein anderes Programm verwenden kann, um auf unsere zuzugreifen Objektregistrierung).

„Mit anderen Worten: Um auf ein Objekt zuzugreifen, müssen Sie die eindeutige Nummer (Port) der Objektregistrierung und den eindeutigen Namen des Objekts kennen und über dieselbe Schnittstelle verfügen wie die, die vom Remote-Objekt implementiert wird.“

„Ich verstehe. Etwas wie: Rufen Sie per Telefon an (brauchen Sie eine Nummer) und fragen Sie nach Bill (dem Namen eines Objekts)?“

„Ja. Jetzt lass uns weitermachen.“

In Zeile 11  erstellen wir einen Stub. Ein Stub ist ein spezielles Objekt, das Informationen über den Remote-Aufruf empfängt, sie entpackt, die Methodenargumente deserialisiert und die erforderliche Methode aufruft. Anschließend serialisiert es das Ergebnis oder die Ausnahme, falls vorhanden und sendet alles an den Anrufer zurück.

„Ich verstehe. Fast. Sie sagten, dass es ‚die Methodenargumente deserialisiert‘. Das bedeutet also, dass die Argumente der Remote-Methoden serialisierbar sein müssen?“

„Ja. Wie sonst soll man sie über das Netzwerk verschicken? Es gibt zwar Ausnahmen, also Objekte, die per Referenz übergeben werden, aber darüber reden wir heute nicht.“

„Wir sagen es so: Sie können keine nicht serialisierbaren Objekte übergeben, aber wenn Sie es wirklich wollen, können Sie es. Aber es ist mühsam, wissen Sie.“

"OK."

„Dann lasst uns weitermachen.“

In Zeile 13 registrieren wir den Stub unseres Objekts unter einem eindeutigen Namen in der Registrierung.“

In Zeile 16 versetzen wir den Hauptthread in den Ruhezustand. Alle Remote-Aufrufe werden in separaten Threads verarbeitet. Wichtig ist, dass das Programm läuft. Also versetzen wir hier einfach den Hauptthread in den Ruhezustand. Das war's.“

"OK."

„Super, dann hier ein Beispiel eines Kunden:“

Arbeiten mit einem Remote-Objekt
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.");
}

„Ich erkläre diesen Code Zeile für Zeile:“

Zeile 1 ist der eindeutige Name  des Remote-Objekts . Dieser muss sowohl auf dem Client als auch auf dem Server gleich sein.“

In Zeile 6  erstellen wir eine „ Registrierung von Remote-Objekten “. Ihr Port (2099) muss mit dem Port der Registrierung für die Serveranwendung identisch sein.“

In Zeile 9 erhalten wir das Objekt aus der Registrierung. Das zurückgegebene Objekt ist ein Proxy-Objekt und wird in eine Schnittstelle konvertiert. Die Schnittstelle muss die Remote-Marker-Schnittstelle erben.“

In Zeile 12 rufen wir die Methoden der Schnittstelle auf, als ob das Objekt im selben Programm erstellt worden wäre. Es gibt keinen Unterschied.“

„Cool! Jetzt kann ich verteilte Anwendungen schreiben. Oder Spiele wie Battleship für Android.“

„Wag es nicht, Amigo! Das Android-Betriebssystem wurde im 27. Jahrhundert nach seinem dritten Versuch, die Welt zu erobern, verboten. Roboter haben überhaupt keinen Zugriff darauf. Es gäbe keine Möglichkeit, dich davon wegzuziehen.“ . Du würdest anfangen herumzurennen und zu rufen: „Töte alle Menschen!“

„Hmm. OK. Aber ich muss Diego trotzdem fragen. Man weiß nie, vielleicht hat er etwas Interessantes dazu zu sagen.“

„Dann geh und frag ihn. Okay, na ja, bis morgen.“

„Tschüs, Rishi. Danke für die interessante Lektion.“