Projektstudium SS98 - distributed computing


vorherige SeiteInhaltnächste Seite

Dynamisches Laden von Klassen

In Systemen, die remote procedure calls verwenden, muß der Stub-Code der Klientseite generiert und mit dem Klient verknüpft sein, bevor ein Methodenaufruf gestartet werden kann. Dieser Stub-Code kann statisch oder aber auch dynamisch über runtime libraries mit den Klient verknüpft werden. Wo die Bibliotheken lokal oder aber auch irgendwo aus dem Netzwerk stammen können. Egal ob nun die Stubs statisch oder dynamisch verknüpft werden, der Client braucht den Code um ein remote procedure call durchführen zu können in kompilierter Form.

 

RMI generalisiert diese Technik, indem es einen Mechanismus benutzt um die Klassen, die zum Aufruf einer Methode eines entfernten Objektes benötigt werden, zur Laufzeit zu laden. Dieser Mechanismus wird dynamisches Laden von Klassen genannt und sorgt dafür, daß folgende Klassen geladen werden:

 

 

Wann wird welcher Class Loader ausgewählt?

 

Der Classloader, der eine Javaklasse läd, wird anschließend dafür genutzt, auch alle weiteren Klassen und Schnittstellen zu laden, die direkt in der zuerst geladen Klasse benutzt werden.

 

 

  1. in dem lokalen Classpath. Klassen werden soweit möglich immer local geladen.
  2. für Objekte (remote und nicht remote), die als Parameter oder Ergebniswert übergeben werden, wird die URL aus dem marshal stream des übersendeten Objektes benutzt, um die Klasse des Objektes zu lokalisieren.
  3. Für Stubs und Skeletons von remote objects, die in der lokalen viruellen Maschine erzeugt wurden, wird die URL benutzt, die durch das lokale java.rmi.server.codebase Attribut bestimmt wurde.

 

Für Objekte, die als Parameter oder Ergebniswert übergeben werden(der zweite Fall), wird die URL aus dem marshal stream des übersendeten Objektes wie folgt bestimmt:

 

 

Folglich,wird das codebase Attribut als URL in einen RMI-Aufruf verwendet, wenn die Klasse lokal aus den Classpath geladen wurde.

 

Die Anwendung kann über das java.rmi.server.useCodebaseOnly Attribut konfiguriert werden. Dieses Atrribut besagt, das alle Klassen und Schnittstellen nur von der lokal definierten Codebase geladen werden, und daher keine Klassen aus dem Netz geladen werden. Wenn die Klassen nicht innerhalb der definierten Prämissen geladen werden kann, wird eine Exeption von der Methode ausgelöst.

 

Es folgt eine Kurzübersicht über die verschiedenen ClassLoader und ihren Verwendungszeitpunkt:

 

 

 

Bootstrapping the Client

Den letzten Punkt der noch besprochen werden muß, um tiefer in die Sicherheitsaspekte von RMI einsteigen zu können, ist die Frage, wie alle benötigten Klassen und Schnittstellen einer Anwendung des Klient geladen werden.

 

Um dieses gewährleisten zu können wird ein bootstrapping Programm auf Seiten des Klients benötigt, welches einen ClassLoader wie den RMIClassLoader statt des standard ClassLoaders verwendet. Folgende Dinge müssen vom bootstrapping Programm durchgeführt werden:

 

 

Ein kleines Beispiel eines bootstrapping Programms:

 

import java.rmi.RMISecurityManager;

 

import java.rmi.server.RMIClassLoader;

 

public class LoadClient

 

{

 

public static void main()

{

 

System.setSecurityManager(new RMISecurityManager());

 

try{

 

Class cl = RMIClassLoader.loadClass("myclient");

Runnable client = (Runnable)cl.newInstance();

 

client.run();

 

} catch (Exception e) {

 

System.out.println("Exception:" + e.getMessage());

 

e.printStackTrace();

}

 

}

 

}

 

 

Wir sehen in diesen kleinen Beispiel noch einmal die 4 Schritte, die von ihrer Reihenfolge nicht verändert werden dürfen.

 

Wesentlich ist, das als wirklich erste Aktion der RMISecurityManager erzeugt und im System mit der Methode setSecurityManager eingetragen wird. Erst jetzt wird über den RMIClassLoader die Klasse "myclient" des Klients geladen. Währe an dieser Stelle kein SecurityManager installiert, so würde der Ladevorgang abgebrochen und eine Exception ausgelöst werden.

 

Wurde die Klasse "myclient" erfolgreich geladen, so wird mit der Methode newInstance eine Instanz der Klasse erzeugt und diese über die expliziete Typtransformation (Runnable) in den ausführbaren Typ umgewandelt.

Im nächsten Schritt wird der Klient über die Methode run() gestartet.

 

Um das Bootstrapping-Programm zum ordnungsgemäßen Laufen zu bekommen, muß noch das java.rmi.server.codebase Attribut definiert werden. Dieses ist notwendig, damit die Methode loadClass vom Bootstrapping-Programm die richtige URL benutzt, um die Klasse "myclient" zu laden.

 

Als Beispiel kann dies beim Starten der Klasse LoadClient geschehen:

 

java -Djava.rmi.server.codebase=http://host/rmiclasses/ LoadClient

 

Anstatt sich auf das Attribut codebase zu beziehen, kann eine eigene URL auch direkt als Parameter der Methode loadClass übergeben werden:

 

Class cl = RMIClassLoader.loadClass(url, "myclient");

 

Wenn der Klient gestartet wurde und die Kontrolle übernommen hat, dann werden alle Klassen und Schnittstellen, die der Klient benötigt, von der definierten URL geladen. Diese bootstrapping Technik ist genau die gleiche, die Java verwendet, um den AppletClassLoader zu veranlassen, alle Klassen zu laden, die von einen Java-Applet benötigt werden.

 

Ohne diese bootstrapping Technik, müßten alle Klassen, die direkt im Programmcode des Klient referenziert wurden, über den lokalen Classpath beim Klient erreichbar sein. Dann wären alle Javaklassen, die vom RMIClassLoader aus dem Netz geladen werden könnten, die welche nicht direkt referenziert werden. Solche Klassen währen dann nur die schon im vorherigen Abschnitt erwähnten Stubs, Skeletons und erweiterte Klassen von Argumenten und Ergebniswerten von remote method Aufrufen.

 

Nun haben wir kennen gelernt, wie von wem unter welchen Voraussetzungen welche Javaklassen geladen werden. Dies ist ein wichtiger Verständnispunkt, um die Philosophie oder auch Idee zu verstehen, die hinter dem Sicherheitskonzept von RMI und auch gerade Jave steht.

 

In dem nun folgenden Abschnitt werden wir das von RMI verfolgete Sicherheitkonzept etwas genauer beleuchten und die Aufgaben des SecurityManagers aufbrechen.

 

vorherige SeiteInhaltnach obennächste Seite 


© Copyright 1998 André Möller, Oliver Mentz & Magnus Wiencke