~/blog/2011/07/java-7-ist-da-hotspot-bug.md

Java 7 ist da – aber Vorsicht beim Hotspot-Bug

3 min
Titelbild: Java 7 ist da – aber Vorsicht beim Hotspot-Bug

Keine Zeit? Hier die Kurzversion in 30 Sekunden.

  • Java 7 ist seit dem 28. Juli 2011 erhältlich, die erste große Java-Version seit Java 6 aus dem Jahr 2006.
  • Neu sind unter anderem Diamond-Operator, Strings im switch, try-with-resources, Multi-Catch und Binärliterale (Project Coin).
  • Die Entwickler von Apache Lucene und Solr warnen vor Fehlern in den Loop-Optimierungen des HotSpot-Compilers.
  • Das kann zu falschen Ergebnissen oder Abstürzen führen, auch bei Java 6 mit -XX:+AggressiveOpts.
  • Workaround ist -XX:-UseLoopPredicate, ein Update ist angekündigt. Für den Produktiveinsatz würde ich auf das Update warten.

Fünf Jahre hat es gedauert, jetzt ist Java 7 fertig. Seit Donnerstag gibt es die Version zum Download, und ich habe sie gleich ausprobiert. Es gibt aber eine Warnung, die man vor dem Umstieg unbedingt kennen sollte.

Was ist neu?

Die Sprache selbst bekommt ein paar kleine Verbesserungen, die unter dem Namen Project Coin laufen. Ich zeige sie mal an einem Beispiel, das alle auf einmal verwendet:

import java.io.*;
import java.util.*;

public class Demo {

    public static void main(String[] args) {
        // Diamond: Typargumente werden aus der linken Seite abgeleitet
        Map<String, List<Integer>> werte = new HashMap<>();
        List<Integer> liste = new ArrayList<>();
        werte.put("klein", liste);

        // Strings im switch
        String befehl = args.length > 0 ? args[0] : "hilfe";
        switch (befehl) {
            case "start":
                System.out.println("Los geht's");
                break;
            case "hilfe":
                System.out.println("Hilfe");
                break;
            default:
                System.out.println("Unbekannt: " + befehl);
        }

        // Zahlenliterale mit Unterstrichen und binär
        int million = 1_000_000;
        int maske = 0b1010_1010;

        // try-with-resources und Multi-Catch
        try (BufferedReader r = new BufferedReader(new FileReader("daten.txt"))) {
            System.out.println(r.readLine());
        } catch (FileNotFoundException | IllegalStateException e) {
            System.out.println("Datei fehlt: " + e.getMessage());
        } catch (IOException e) {
            System.out.println("Lesefehler: " + e.getMessage());
        }
    }
}

Der Reader wird am Ende des try-Blocks automatisch geschlossen, das finally mit dem close() entfällt. Das ist die Änderung, die ich am häufigsten brauchen werde. Die Reihenfolge der catch-Zweige ist wie immer wichtig: FileNotFoundException ist eine Unterklasse von IOException, deshalb steht sie vorne. Außerdem gibt es mit NIO.2 eine neue Dateisystem-API und das Fork/Join-Framework für parallele Aufgaben. Dazu schreibe ich demnächst einen eigenen Artikel.

Zum Diamond noch ein Wort: Er spart vor allem bei verschachtelten Generics Tipparbeit, bei Methodenaufrufen als Argument leitet Java 7 den Typ allerdings nicht ab. Deshalb steht im Beispiel die Liste erst in einer eigenen Variable. Und bei Strings im switch wird intern equals() verwendet, ein null als Wert wirft also wie immer eine NullPointerException.

Der Haken: HotSpot und die Schleifen

Kurz vor dem Release haben die Entwickler von Apache Lucene und Solr eine Warnung veröffentlicht. Nach ihren Angaben können Optimierungen von Schleifen im HotSpot-Compiler zu falschen Ergebnissen oder sogar zu Abstürzen der JVM führen. Betroffen ist nicht nur Java 7, sondern auch Java 6, wenn man die Option -XX:+AggressiveOpts einschaltet. Gerade bei Suchindizes ist das unangenehm, weil man falsche Ergebnisse nicht sofort bemerkt. Als Workaround wird empfohlen, die Optimierung abzuschalten:

java -XX:-UseLoopPredicate -jar meineanwendung.jar

Das kostet vermutlich etwas Geschwindigkeit, wie viel, kann ich nicht sagen. Von Oracle ist ein Update angekündigt, das das Problem beheben soll. Ob und wann es kommt, weiß ich nicht.

Meine Empfehlung

Zum Ausprobieren und Spielen ist Java 7 völlig in Ordnung, und die neuen Sprachmerkmale kann man ja auch mit einem Projekt testen, das nicht produktiv läuft. Für alles, was in Produktion geht oder mit Lucene, Solr oder ähnlichen Bibliotheken arbeitet, würde ich auf das erste Update warten und es dann mit der Option testen. Und wer Java 6 mit -XX:+AggressiveOpts betreibt, sollte das jetzt prüfen. Normalerweise sind die ersten Versionen einer großen Java-Version ohnehin nicht die, die ich auf Server loslassen würde.

Habt ihr Java 7 schon installiert? Was gefällt euch am besten, und werdet ihr gleich umsteigen?

$ whoami
Christian Ackermann

Softwareentwickler (C++, C, Java, C#) aus der Oberpfalz, bloggt seit 2001 über Linux, Technik und Kochen.