Dynamic Code Evolution für Java

Marc Teufel

Das kostenlose Tool Dynamic Code Evolution (DCE) bietet gute Möglichkeiten, Java-Programme zur Laufzeit zu bearbeiten und Änderungen direkt zu testen. Gerade für Entwickler lässt sich somit die Entwicklungszeit reduzieren. So gesehen könnte man DCE mit JavaRebel vergleichen, muss man aber nicht. Wir klären warum.

DCE versus JavaRebel?

Man könnte DCE nun mit dem kommerziellen Werkzeug JavaRebel aus dem Hause Zero Turnaround vergleichen, doch beim genauen Hinschauen erkennt man, dass sich beide Produkte nicht nur technisch, sondern auch im täglichen Einsatz durchaus voneinander unterscheiden. Genau genommen verfolgt DCE auch andere Ziele als sein kommerzieller Konkurrent.

Während sich JavaRebel über den Parameter -javaagent in eine laufende VM einklinkt, handelt es sich bei DCE selbst um eine modifizierte VM. Die Grundlage hierfür bildet dabei die Java HotSpot VM, die selbst bereits ein Austauschen von Methoden einer Klasse zur Laufzeit ermöglicht. DCE erweitert diese Technik nun um zusätzliche Möglichkeiten: So kann man jetzt zu jedem Zeitpunkt während der Ausführungszeit des Programmes Methoden und Felder zu Klassen hinzufügen und entfernen, man kann Oberklassen modifizieren, neue Klassen hinzufügen, entfernen und so weiter.

Auch für die Serverseite in der Produktion könnte DCE in Zukunft interessant werden, denn nun könnte man zur Laufzeit eine ganze Anwendung oder Teile davon austauschen, ohne die Anwendung neu deployen oder gar einen Neustart des Servers durchführen zu müssen. Man könnte DCE auch im Sinne von aspektorientierter Programmierung einsetzen (Stichwort Mixins, siehe weiter unten), etwa zum dynamischen Hinzufügen von zusätzlichem Logging vor und nach Aufruf bestimmter Methoden – wohlgemerkt dynamisch zur Laufzeit der Anwendung.

Installation

Die Entwickler von DCE empfehlen derzeit jedoch klar, das Werkzeug zunächst nur auf dem Entwicklungsrechner beim Entwickeln und Debuggen einer Anwendung einzusetzen. Hierfür ist DCE laut Projektseite performant und stabil genug. Von einer Installation auf einem Server wird derzeit noch abgeraten. DCE liegt aktuell in einer Version für 32- und 64bit Windows vor. Für Mac OS X und Linux stehen 32bit-Versionen zum Download bereit. Installiert wird die Software über einen eigenen Installer. Hierzu muss mindestens ein JRE oder JDK vorhanden sein. Den Installer startet man recht einfach mit

sudo java -jar dcevm-020.jar

Wichtig dabei ist, dass man die Installationsroutine immer mit Administator-Rechten startet. Der Installer (Abbildung 1) listet alle Java-Installationen auf dem Sytem auf, alternativ kann man mit Hilfe des Knopfes Add installation directory… nicht automatisch erkannte Java-Installationen hinzufügen. In der Liste (Spalte DCE) kann man sehen, ob das Werkzeug in der entsprechenden Java-Installation schon hineininstalliert wurde oder nicht. Der Installer ersetzt die Datei jvm.dll in den Verzeichnissen bin/client und bin/server. Die Original-Datei wird als Backup zur Seite kopiert. Darüber hinaus kopiert der Installer die Datei dcevm.jar in das Verzeichnis lib/ext der entsprechenden Java-Installation (wichtig für Mixins). Prüfen, ob die Installation erfolgreich war, kann man direkt im Installer, indem man auf den Knopf Test installation klickt. Alternativ kann man auf der Konsole auch ein java -version eingeben (Abbildung 2), woraufhin nicht nur die Version der installierten Java-Version, sondern zusätzlich auch der Versionshinweis von DCE erscheint.

Abbildung 1: Der DCE Installer in Aktion

Abbildung 2: DCE klinkt sich direkt in das installierte Java ein, wie java -version beweist…
Ausprobieren

Ab sofort kann man im Entwicklungsprozess zur Laufzeit einer Anwendung Klassen austauschen, neue Hinzufügen und so weiter. Wichtig dabei ist jedoch, dass die Anwendung unbedingt im Debug-Modus gestartet ist. Im Folgenden soll dies anhand der Eclipse-RCP-Mail-Beispielanwendung gezeigt werden.

Nachdem man sich das Beispielprojekt generiert hat, startet man die Mail-Anwendung im Debug-Modus. Wenn man in der Beispielanwendung auf das Plus-Symbol klickt, wird eine neue Instanz der View geöffnet, welche nun zur Laufzeit geändert werden soll. Hierzu öffnet man am besten die View-Klasse im Projekt und verändert etwa die Codezeile, die den Betreff setzt. Wichtig dabei ist natürlich, dass die Anwendung im Debug-Modus weiter läuft, während man die Änderung am Code durchführt. Nach dem Speichern der Änderung in der View-Klasse sollte diese sofort aktiv werden, was sich beweisen lässt, wenn man erneut das Plus-Symbol drückt. Aber funktioniert das auch, wenn man gänzlich neue Klassen in die laufende Anwendung einbringen will? Um dies herauszufinden, legt man am besten eine neue Klasse namens TestDialog an, die von TitleAreaDialog erbt:

Listing 1: Einfaches Beispiel für einen TitleAreaDialog

public class TestDialog extends TitleAreaDialog {
    
     public TestDialog(Shell shell) {
        super(shell);
        setTitle("About This Application");
        setMessage("This is a JFace dialog", IMessageProvider.INFORMATION);
     }

     protected Control createContents(Composite parent) {
        Control contents = super.createContents(parent);
        setTitle("About This Application");
        setMessage("This is a JFace dialog", IMessageProvider.INFORMATION);
        return contents;
     }

    protected Control createDialogArea(Composite parent) {
        Composite composite = (Composite) super.createDialogArea(parent);
        return composite;
    }

}

Den neuen Dialog kann man nun an das zweite Icon in der Toolbar hängen, indem man die Klasse MessagPopupAction entsprechend anpasst.

Listing 2: Den TitleAreaDialog zur Laufzeit in die bestehende Action einbinden

public void run() {
    TestDialog testDialog = new TestDialog(window.getShell());
    testDialog.open();
    // alter Code :
    // MessageDialog.openInformation(window.getShell(), "Open", "Open Message Dialog!");
}

Tut man all dies, während die RCP-Mail-Anwendung weiter im Debug-Mode läuft, wird die neue Dialog-Klasse ebenso sofort aktiv. Wie man unschwer erkennen kann, beschleunigt diese Vorgehensweise den Entwicklungsprozess deutlich, da das ständige Neustarten der sich gerade in Bearbeitung befindlichen Anwendung wegfällt.

Mixins

Ein weiteres besonderes Feature von DCE ist die Möglichkeit, Klassen nicht nur während des Debuggens aus einer Entwicklungsumgebung heraus zu modifizieren. DCE bietet zusätzlich ein API an, um Klassen dynamisch zur Laufzeit zu erweitern. Dieses Verfahren nennt sich Mixins, auf der Projektseite findet sich hierzu ein Beispiel inklusive Beschreibung. Die Idee dabei ist, durch eine von DCE bereitgestellte addMixin-Methode beliebig viel Funktionalität zu einer bestehende Klasse hinzuzufügen. Damit dieses Feature jedoch funktionieren kann, muss, ähnlich JavaRebel, DCE über den Schalter -javaagent zusätzlich aktiviert werden:

java-javaagent:/PATH_JDK/lib/ext/dcevm.jar
Zusammenfassung

Der Artikel hat gezeigt, dass man DCE durchaus mit JavaRebel vergleichen kann, beide Produkte sich im Detail aber voneinander unterscheiden. Im Gegensatz zu JavaRebel ersetzt DCE die bestehende Java HotSpot VM durch eine modifizierte Version, mit der eine Vielzahl von Modifikationen und Erweiterungen in laufenden Java-Anwendungen durchgeführt werden kann. Hierdurch eignet sich DCE vor allem zum Einsatz beim Entwickeln und Debuggen, da eventuelle zeitintensive Neustart- und Initialisierungszeiten deutlich minimiert werden können. DCE soll man in Zukunft auch auf Server-Seite einsetzen können, man erhofft sich hierdurch die Möglichkeit, Teile von produktiven Systemen zur Laufzeit ohne Stop der Anwendung austauschen zu können. Ferner bietet DCE mit Mixins ein API an, mit dem sich zur Laufzeit Klassen dynamisch erweitern lassen.

Marc Teufel arbeitet als Software-Architekt bei der hama GmbH & Co und ist dort für die Entwicklung großer Java-Anwendungen im Logistikzentrum zuständig. Er ist Autor zahlreicher Fachartikel zu Java und .NET, hat drei Bücher zu Web Services publiziert und spricht regelmäßig auf Fachkonferenzen. Unter www.teufel.net ist er im Web zu erreichen.

Geschrieben von
Marc Teufel
Kommentare

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.