4.15.2 | Die Klasse ClassLoader |
Für den eigentlichen Ladevorgang ist die Klasse ClassLoader aus dem Paket java.lang zuständig. Zum Laden einer Klasse muss ein ClassLoader im Wesentlichen zwei Schritte durchführen:Jede Virtual Machine erzeugt standardmäßig ein Exemplar dieser Klasse, den so genannten System-ClassLoader. Dieser System-ClassLoader kann Klassen aus .class-Dateien oder .jar-Archiven vom lokalen Dateisystem laden. Um diese Dateien zu lokalisieren, wertet der System-ClassLoader die Umgebungsvariable CLASSPATH aus. Eine Referenz auf den System-ClassLoader kann mit der Methode ClassLoader.getSystemClassLoader() ermittelt werden.
- Er muss den Bytecode der Klasse in spezifischer Weise in ein byte-Array einlesen (z. B. aus einer lokalen Datei oder über Netzwerk).
- Er muss im zweiten Schritt aus diesem byte-Array eine Klasse in der Virtual Machine erzeugen, in dem die Methode defineClass() aufgerufen wird.
Jeder anwenderdefinierte ClassLoader ist mit dem System-ClassLoader verkettet, entweder direkt oder indirekt über andere ClassLoader. Durch diese Kette wird ein Delegationsmodell realisiert, das standardmäßig folgendermaßen abläuft:Durch diesen Mechanismus wird jede Anfrage zunächst bis zum System-ClassLoader weiterpropagiert. Wenn dieser die Klasse nicht findet, läuft die Anfrage die Kette »rückwärts« zurück, bis ein ClassLoader die Klasse findet.
- Ein ClassLoader erhält durch den Aufruf seiner Methode loadClass() die Aufforderung, eine bestimmte Klasse zu laden.
- Der ClassLoader leitet die Anfrage zunächst an den übergeordneten ClassLoader weiter. Nur wenn dieser die Klasse nicht findet, versucht er selbst, die Klasse zu laden.
Der übergeordnete ClassLoader kann optional im Konstruktor angegeben werden. Fehlt diese Angabe, wird automatisch der System-ClassLoader als übergeordneter ClassLoader verwendet.
Der geschilderte Verkettungsmechanismus ist in der Methode ClassLoader.loadClass() implementiert. Wenn ein anderes Verhalten gewünscht wird, muss diese Methode überschrieben werden.
Wenn dieses Delegationsmodell dagegen übernommen werden soll, genügt es, die Methode findClass() zu überschreiben und dort die anwenderdefinierte Logik zum Einlesen des Bytecodes zu implementieren. Alle anderen Methoden können dann belassen werden.
Das folgende Beispiel realisiert einen ClassLoader, der Bytecode aus verschlüsselten Dateien lesen kann. Die Verschlüsselung erfolgt mit dem Triple-DES-Algorithmus anhand eines hart in der Klasse kodierten Schlüssels. Diese Art der Sicherung bietet zwar nur begrenzten Schutz gegen einen ambitionierten Angreifer, sie wirkt aber gegen Ad-hoc-Versuche zur Disassemblierung.
Um Bytecode-Dateien zu verschlüsseln, verfügt die Klasse über eine main()-Methode, mit der die Klasse wie eine Applikation aufgerufen werden kann. Als Argumente werden die Namen der zu verschlüsselnden .class-Dateien angegeben.
Die Entschlüsselung erfolgt in der Methode findClass(). Nach dem Einlesen des Bytecodes wird die von ClassLoader bereitgestellte Methode defineClass() aufgerufen, um aus dem Bytecode ein Class-Objekt zu erzeugen.public Class findClass(String name) throws ClassNotFoundException { // Dieses Array nimmt den Bytecode auf. byte[] byteCode = null; // Zusammensetzen des Dateinamens String fileName = name.replace('.', File.separatorChar)+"."+CRYPT_EXT; try { // Entschlüsseln der Datei und Einlesen des Bytecodes byteCode = decryptFile(fileName); } catch(IOException e) { throw new ClassNotFoundException("Encrytepd class " +name+" not found.", e); } // Klasse in der VM erzeugen und Class-Objekt zurückliefern Class c = defineClass(name, byteCode, 0, byteCode.length); return c; }Mit dem letzten Schritt wird der Bytecode gewissermaßen bei der Virtual Machine als Klasse registriert. Dabei wird auch ein Class-Objekt für die neue Klasse erzeugt und von defineClass() zurückgeliefert. Dieses Class-Objekt kann dann als Rückgabewert in findClass() verwendet werden.
Die Mechanismen zur Ver- und Entschlüsselung von Dateien, die in diesem Beispiel verwendet werden, werden ausführlicher im Abschnitt 15.2.3 behandelt. Auch dort wird ein Beispiel zur Verschlüsselung von Dateien behandelt.