8.4 Kompilieren von Klassen
 
Die Klassenbibliothek von Java bietet zwei unterschiedliche Techniken zum Übersetzen von Klassendateien. Die eine Methode steuert die Übersetzung einer geladenen Klasse von der Repräsentation in der JVM in eine die Geschwindigkeit steigernde Darstellung mit Hilfe eines Just-In-Time-(JIT) Compilers. Die andere Technik basiert auf der Idee, den Original-Compiler von Sun zu nutzen, dessen Schnittstelle ebenfalls in Java programmiert ist und als Klasse dem JDK beiliegt. Auf diese Weise kann ein laufendes Programm einen (selbst erzeugten) Java-Quelltext übersetzen und die darin definierten Klassen anschließend sofort benutzen.
8.4.1 Der Sun-Compiler
 
Besteht der Wunsch, aus einem Java-Programm heraus den Compiler zu benutzen, so ist die eine Möglichkeit der Einsatz der Methode System.exec(). Doch es gibt auch einen anderen Weg. Er nutzt aus, dass auch der Sun-Compiler in Java programmiert ist. Er nutzt jedoch nicht die compileClasses()-Methoden der Klasse Compiler, da er direkt aus dem Quelltext des Programms Bytecode erstellt. Der Compiler liegt dem JDK nicht als Quellcode bei, jedoch ist die Klasse sun.tools.javac.Main in der Jar-Datei lib/tools.jar zu finden – und gegebenenfalls durch einen Disassembler oder Decompiler zu entschlüsseln. Für uns ist es also äquivalent, ob wir nun
$ javac test.java
oder
$ java sun.tools.javac.Main test.java
schreiben. Das Binärprogramm javac fügt nichts Großartiges hinzu, außer vielleicht, dass es noch die Heap-Größe setzt. Ein Aufruf des javac-Kommandos in exec() muss prinzipbedingt länger dauern als ein direkter Aufruf der main()-Methode des Compilers. Beim javac-Kommando muss das Betriebssystem einen neuen Prozess erzeugen, eine zweite JVM wird geladen, die wieder alle dreihundert benötigten Standardklassen lädt und vom JIT-Compiler übersetzen lässt.
Den Sun-Compiler im eigenen Programm benutzen
Nicht nur die main()-Methode ist öffentlich, auch innerhalb eines eigenen Java-Programms können wir den Compiler gezielt benutzen. Dies geschieht mit dem Aufruf der Funktion compiler() aus der Klasse Main. Eine Erzeugung der Klasse Main im Paket javac mit den Parametern des Konstruktors sieht folgendermaßen aus:
sun.tools.javac.Main jc = new sun.tools.javac.Main( System.out,"javac" );
if ( !jc.compile(args) )
// Hilfe, keine .class Datei
Im String args stehen die Argumente der Kommandozeile sowie die des Klassenpfads.
Die API ist nicht öffentlich und bei dem Einsatz der Methode ist Vorsicht geboten, denn sie braucht in zukünftigen Versionen des JDK nicht mehr zu existieren. Da das Paket sun.tools.javac nicht dem JRE (Java Runtime Environment) beiliegt – nur zum Ausführen, aber nicht zum Entwickeln von Java-Programmen gedacht –, laufen keine Programme, die den Java-Compiler aufrufen. Das gilt für beide Techniken zum Aufruf des Compilers, also der Klasse sun.tools.javac.Main und der Methode Runtime.exec().
|