Freitag, 13. November 2009

VisualVM 1.2

Nachdem im Oktober Version 1.2 des Monitoring- und Profiling-Werkzeugs VisualVM veröffentlicht wurde, folgte Anfang dieser Woche das Bugfix-Release 1.2.1. Beide Versionen basieren auf dem Profiler von NetBeans 6.7.1.

Neu ist u.a. die stabile Version des "Sampler"-Plugins, mit dem schnell ein einfaches (aber oft schon vollkommen ausreichendes) CPU- und Speicher-Profiling durchgeführt werden kann. Wie die übrigens Plugins muss auch dieses im Menü Tools > Plugins installiert werden:

Außerdem kann man nun endlich eventuell notwendige Proxy-Einstellungen innerhalb von VisualVM vornehmen. Weitere Änderungen und Ergänzungen sind hier aufgelistet.

Dienstag, 3. November 2009

Java EE SDK unter Snow Leopard installieren

Mac OS X 10.6 "Snow Leopard" enthält Java SE 6 als einzige Java-Laufzeitumgebung (und nicht mehr Java 1.4, 5.0 und 6 wie Mac OS X 10.5). Das bringt ein Problem mit sich, wenn man Suns aktuelles Java EE 5 SDK Update 7 installieren möchte, denn das Installationsskript ist fest verdrahtet auf ein installiertes Java 5 angewiesen. Im System sind zwar die Ordner für Java 5.0 vorhanden, die verweisen aber auf die Java 6-Installation – und das reicht dem Skript leider nicht aus.

Im konkreten Fall haben wir das Archiv java_ee_sdk-5_07-mac-nojdk.zip (Download "GlassFish Java EE") ausgepackt und zu installieren versucht:

HeartOfGold:java_ee_sdk-5_07-mac-nojdk much$ chmod a+rx setup
HeartOfGold:java_ee_sdk-5_07-mac-nojdk much$ ./setup
Installer cannot find a suitable 1.5.x version of JDK under the
following directories.

1. /System/Library/Frameworks/JavaVM.framework/Versions/1.5.0/Home
2. /Library/Java/Home

Please rerun with -javahome argument pointing to a valid 1.5 version of JDK.

Zum Glück ist die Lösung recht einfach (man muss dafür kein altes Java 5.0 aus Mac OS X 10.5 installieren). In der Skript-Datei setup ersetzt man mit einem Texteditor in Zeile 54 einfach am Ende der Zeile "1.5" durch "1.6":
54: javaVersion=`${TIGER_JAVAHOME} ... ${GREP} 1.6`
Das war es dann auch schon! Der Installer lässt sich nun auch mit Java 6 problemlos ausführen, und GlassFish läuft auch (bzw. gerade) mit dem aktuellen JRE hervorragend.

Donnerstag, 15. Oktober 2009

IntelliJ IDEA 9: Community Edition und Open Source

Die Entwicklungsumgebung IntelliJ IDEA ist seit längerem der Geheimtipp für Java-Entwickler. Doch während Eclipse und NetBeans kostenlos erhältlich und weit verbreitet sind, schreckten viele vor dem dreistelligen Kaufpreis für eine IDE(A) zurück.

Mit der kommenden Version 9.0 wird IntelliJ IDEA nun Open Source und steht seit heute auch in einer kostenlosen Community Edition zur Verfügung. Mit dieser Edition kann Java SE, Groovy und Scala programmiert werden (inkl. Debugging, Refactoring, Testen, Versionsverwaltung etc.).

Für die Entwicklung von Web- und Enterprise-Applikationen wird die weiterhin kostenpflichtige Ultimate Edition benötigt, die neben aktuellen und künftigen Standards (Java EE 6 etc.) zahlreiche Programmiersprachen, Frameworks und Versionsverwaltungssysteme zusätzlich unterstützt.

Fazit: Für professionelle JEE-Entwicklung ist zwar nach wie vor die kostenpflichtige Ultimate Edition notwendig, aber zumindest kann sich nun jeder einen ausführlichen Eindruck von IntelliJ verschaffen. Und das hat diese Entwicklungsumgebung durchaus verdient.

Dienstag, 13. Oktober 2009

Snow Leopard und Rosetta

Schon seit den ersten Mac OS X-Versionen können Java-Applikationen in einer speziellen Verzeichnisstruktur als "normale" Mac OS X-Anwendung verpackt werden, so dass sie u.a. mit einem eigenen Programmsymbol dargestellt werden. Damit solche Application Bundles Java-Bytecode ausführen können, enthalten sie als nativen Mach-O-Startcode im Verzeichnis /Contents/MacOS/ die Datei JavaApplicationStub:

Führt man ältere, noch unter PowerPC (PPC) Mac OS X zusammengebaute Java-Application-Bundles unter Mac OS X 10.6 "Snow Leopard" aus, erhält man eventuell den Hinweis, dass man den auf der Snow-Leopard-Installations-DVD enthaltenen PPC-Emulator "Rosetta" installieren muss, um die Anwendung starten zu können. Obwohl Apple seit Mac OS X 10.4 alte PPC-JavaApplicationStubs erkennt und als 32-Bit-Intel-Prozess neu startet, muss dafür Rosetta installiert sein – und genau das ist seit Snow Leopard nicht mehr standardmäßig der Fall.

Die einfachste Lösung, die zudem Rosetta nicht benötigt, ist, den alten Stub im Application Bundle durch eine Kopie der aktuelle Version /System/Library/Frameworks/JavaVM.framework/Resources/MacOS/JavaApplicationStub zu ersetzen. Dieser neue Stub enthält Code für die drei derzeit unterstützten Prozessorarchitekturen:
Straylight:~ much$ file JavaApplicationStub
JavaApplicationStub: Mach-O universal binary with 3 architectures
JavaApplicationStub (for architecture x86_64): Mach-O 64-bit executable x86_64
JavaApplicationStub (for architecture i386): Mach-O executable i386
JavaApplicationStub (for architecture ppc7400): Mach-O executable ppc
Wenn eine Java-Anwendung eine bestimmte Architektur nicht benötigt (z.B. weil nachgeladene JNI-Bibliotheken dafür nicht compiliert wurden), kann und sollte der entsprechende Code mit /usr/bin/lipo entfernt werden.

Dienstag, 1. September 2009

Java in Mac OS X 10.6 "Snow Leopard"

Der Schneeleopard ist also aus dem Käfig... Und während das nun "alte" Mac OS X 10.5 noch drei Implementierungen für Java 1.4, 5.0 und 6 mitbrachte, enthält Mac OS X 10.6 ausschließlich Java SE 6 (1.6.0_15) in einer 32-Bit- und einer 64-Bit-Version. Detaillierte Informationen zu beseitigten und bekannten Fehlern enthalten die Release Notes.

Damit auch Java 5-Anwendungen weitestgehend problemlos laufen, sind im Ordner /System/Library/Frameworks/JavaVM.framework/Versions noch die Unterordner 1.5 und 1.5.0 enthalten, aber beide sind Aliase (Symlinks) auf die Java 6-Implementierung.

Und obwohl QuickTime for Java schon seit längerem nicht mehr offiziell unterstützt wird, sind die QTJava-Bibliotheken immer noch vorhanden und funktionieren auch mit Java 6.

Mal abwarten, was die praktischen Erfahrungen in den kommenden Tagen zeigen.

Mittwoch, 26. August 2009

Closures in JavaFX Script

JavaFX Script (die Programmiersprache für Suns neue RIA-Technologie JavaFX) ist eine objektorientierte, deklarative und funktionale Programmiersprache.

Als funktionale Sprache unterstützt sie Funktionen höherer Ordnung (first-class functions) und Funktionsabschlüsse (Closures). Ersteres bedeutet, dass Funktionen selber Werte sind – sie können also als Parameter übergeben und zurückgegeben werden. Letzteres erlaubt den Funktionswerten, dass sie sich den Zustand ihrer Umgebung (die lokalen Variablen) bei ihrer Erzeugung merken können.

Für viele sind Closures seltsame Konstrukte und ihre Einsatzmöglichkeiten nicht offensichtlich. Daher im Folgenden ein kleines, relativ leicht verständliches Beispiel, in dem mehrere Zähler mit individuellen Startwerten erzeugt und benutzt werden:
// closure.fx

function zaehlerMitStartwert(startwert: Integer) {
var n = startwert;
return function(): Integer { return n++ }
}

var next1 = zaehlerMitStartwert(10);
var next2 = zaehlerMitStartwert(20);

println( next1() ); // 10
println( next2() ); // 20
println( next2() ); // 21
println( next1() ); // 11
Wer das Beispiel ausprobieren möchte, installiert sich das JavaFX 1.2 SDK und nutzt die Kommandozeile (oder NetBeans oder Eclipse mit dem JavaFX-Plugin):
Straylight:~ much$ javafxc closure.fx
Straylight:~ much$ javafx closure
10
20
21
11
Die ausgegrauten Elemente sind nicht wirklich notwendig und sollen nur das Skript für Java-Programmierer leichter verständlich machen. "return" ist an beiden Stellen optional, da der letzte Ausdruck in einer Funktion gleichzeitig deren Ergebnis definiert. Der Rückgabetyp ":Integer" der inneren, anonymen Funktion ist optional, da aus dem Datentyp des Ergebnisses der Rückgabetyp durch Typinferenz ermittelt werden kann.

Trotz (bzw. gerade wegen) dieser impliziten Typisierung ist JavaFX Script im Gegensatz zu Skriptsprachen wie JavaScript statisch und streng typisiert. Bereits der Compiler ermittelt also die Datentypen und Signaturen von Variablen und Funktionen, sofern sie nicht explizit angegeben sind. Im Beispiel hat die Variable n also den Datentyp Integer, die Variablen next1 und next2 haben den Typ function():Integer und zaehlerMitStartwert hat den Typ function(:Integer):function():Integer :-)

Wie funktioniert das Skript? Beim Aufruf der Funktion zaehlerMitStartwert wird eine Funktion zurückgegeben, die bei jedem Aufruf die Variable n um eins erhöht zurückgibt. Obwohl die Variable n zur äußeren Funktion gehört und damit beim Aufruf der zurückgegebenen Funktion mit next1() bzw. next2() eigentlich gar nicht mehr vorhanden ist, merkt sich die innere Funktion die lokale Variable separat für jede zurückgegebene innere Funktion – und genau das macht sie zur Closure.

Man kann sich Closures als Objekte vorstellen, die aus einer einzigen Methode/Funktion bestehen und wie Objekte zusätzlich einen Zustand haben. Schön sehen kann man dies an den generierten Java-Bytecode-Klassendateien: closure.class und closure$1.class. Die innere, anonyme Funktion wird für die JVM also einfach als innere, anonyme Java-Klasse closure$1.class abgebildet.

Closures sind prima geeignet, um damit z.B. Event-Handler zu definieren, denen man zusätzliche Informationen mitgeben kann (bei Farb-Setz-Buttons in einem Grafikprogramm beispielsweise die zu setzende Farbe). Dadurch kann man häufig auf das Schreiben von Event-Handler-Klassen verzichten, auch wenn dies in JavaFX Script ebenfalls möglich ist.

Vielleicht hat man es gemerkt: Ich halte JavaFX Script trotz des Namens ganz und gar nicht für eine Skriptsprache. Meines Erachtens wurde die Sprache vor allem deshalb so genannt, um zu zeigen, dass man damit in Wettbewerb zu Skriptsprachen wie Ruby tritt, die als agil und produktiv empfunden werden. JavaFX Script zeigt dabei sehr schön, dass sich Produktivität und statische, strenge Typisierung überhaupt nicht ausschließen müssen.

Dienstag, 25. August 2009

Hibernate 3.5 und JPA 2.0

Vor wenigen Tagen wurde die erste Betaversion von Hibernate 3.5 veröffentlicht. Sofern der Download von SourceForge klappt, kann man damit viele der Neuerungen von JPA 2.0 ausprobieren.

Hibernate 3.5 bietet keine wesentlichen neuen Hibernate-Features, und auch für die Unterstützung der neuen JPA-Version wurden vor allem standardkonforme Schnittstellen für bereits vorhandene Hibernate-Eigenschaften bereitgestellt. Dies ist wohl auch der Grund, warum die Hibernate-Version nicht gleich auf 4.0 heraufgesetzt wurde.

Schön ist meines Erachtens, dass ab Version 3.5 die JARs für die Hibernate-Annotationen und den JPA-EntityManager Bestandteil vom Hibernate-Kern (Core) geworden sind. Und die Einbindung von Envers dürfte diese Versionierungs-Bibliothek zum heißen Kandidaten für den De-Facto-Standard bezüglich Versionierung/Historisierung/Auditierung mit JPA machen.