Java 7: The Big Update

Project Coin

„Project Coin“ ist eine Sammlung kleinerer Spracherweiterungen (bei dem Projektnamen handelt es sich um ein Wortspiel: das englische Wort „coin“ bedeutet einerseits „Münze“, also „Kleingeld“ oder „Kleinigkeit“; andererseits bezeichnet das Verb „to coin“ das „Prägen“ von Münzen oder auch Begriffen). Die Ideen für diese Ergänzungen stammen aus der Java-Community selbst. Sun Microsystems hatte die Community aufgefordert, entsprechende Vorschläge zu machen, und hatte aus der Fülle der Ideen eine Handvoll aufgegriffen. Die Idee dabei war es, die Sprache um Mittel zu erweitern, die nützlich und „klein“ sind.

In den JDK geschafft haben es folgende Vorschläge:

  • Strings in switch-Anweisungen
  • Verbesserte Schreibweisen für numerische Literale
  • Vereinfachungen beim Aufruf von Methoden mit variabler Argumentenliste
  • Verbesserte Type Inferences für Konstruktoren generischer Typen („diamond operator“)
  • Verbessertes Exception Handling
  • Automatic Resource Management
  • Sprachunterstützung für Collections (Java 8)

Die Sprachunterstützung für Collections ist noch nicht implementiert und deshalb nicht für Java 7 vorgesehen, sondern gleich auf Java 8 verschoben worden. Hier ist zu erwarten, dass die später frei gegebene Implementierung von den heutigen Vorschlägen abweichen wird.

Die „Coin“-Features werden wir uns in den nächsten beiden Beiträgen genauer ansehen.

InvokeDynamic

invokedynamic ist eine neue Bytecode-Instruktion, die den Aufruf von Methoden erlaubt, ohne dass geprüft wird, zu welcher Klasse diese Methode gehört, von welchem Typ ihr Returnwert ist oder welche Methodenparameter sie verwendet. Die bisherigen Bytecode-Instruktionen für den Aufruf von Methoden invokevirtual („normale“ Methodenaufrufe), invokestatic (Aufruf statischer Methoden) und invokespecial (Aufruf von Konstruktoren und Superclass-Methoden) verlangen eine genaue Spezifikation der Methodensignatur. Die Bytecode-Verifikation während des Classloadings prüft diese Bytecode-Instruktionen und weist Aufrufe, für die es keine zur Signatur passende Methode gibt, zurück. Lediglich die Instruktion invokeinterface (Aufruf einer Methode über einen Interfacetyp, d. h. ohne dass festgelegt wäre, zu welcher Klasse die Methode gehört) war etwas gnädiger bei der Prüfung.

All diese Bytecode-Instruktionen sind angelegt für eine statisch geprüfte Sprache wie Java, bei der der Typ jedes Objekts und die gesamte Signatur jeder Methode bereits zur Übersetzungszeit feststehen. Mittlerweile gibt es aber zahlreiche Sprachen auf der JVM, die dynamisch geprüft werden und in denen Methoden eben keine zur Übersetzungszeit festgelegte Signatur haben. Für die Implementierung von dynamischen Sprachen auf der JVM waren deshalb zahlreiche Klimmzüge nötig, um die Methodenaufrufe zu bewerkstelligen. Die neue Bytecode-Instruktion invokedynamic löst diese Probleme. Java-Entwickler werden mit invokedynamic nicht in Berührung kommen, weil der Java-Compiler diese Instruktion nicht verwendet.

Concurrency Utilities

Unter der Bezeichnung „jsr166y“ werden Ergänzungen zum Concurrency Support des JDK verstanden. Beschrieben sind die Neuerungen im JSR 166, den Doug Lea seit Java 5 stetig weiterpflegt. In Java 5 gab es den JSR166, in Java 6 den JSR166x und in Java 7 kommt nun JSR166y hinzu [3]. Es gibt außerdem noch einen Teil JSR166yextra, der auf Java 8 verschoben wurde, weil er ohne das Sprachmittel der Lambdas nicht gut benutzbar ist. Dabei geht es um Parallel Arrays, d. h. um die Parallelisierung von Array-Zugriffen.

Die wesentliche Neuerung für Java 7 ist ein Framework für die Parallelisierung von rekursiven Aufgaben, Fork/Join Framework genannt. Dabei handelt es sich um einen speziellen Thread Pool für Tasks, die sich rekursiv in Subtasks zerlegen, diese Subtasks starten, auf die Teilergebnisse warten und daraus ein Gesamtergebnis produzieren. Da solche Aufgaben voneinander abhängen – jede Task wartet auf das Ergebnis ihrer Subtasks – ist der herkömmliche, bereits seit Java 5 im JDK enthaltene Thread Pool (Klasse ThreadPoolExecutor) ungeeignet. Er ist für voneinander unabhängige Tasks gedacht. Deshalb gibt es mit der Klasse ForkJoinPool eine Thread-Pool-Implementierung, die für das Abarbeiten rekursiver Aufgaben angelegt ist. Die für Java 8 angekündigten Parallel Arrays werden übrigens auf diesem Fork/Join Framework aufsetzen.

Neben dem Fork/Join Framework kommt mit Java 7 die Abstraktion Phaser zum Package java.util.concurrent hinzu. Der Phaser ist eine flexiblere Variante der seit Java 5 existierenden CyclicBarrier. Während sich an einer CyclicBarrier eine fixe Anzahl von Threads trifft und aufeinander wartet, erlaubt der Phaser eine variable Anzahl von beteiligten Parteien.

Eine weitere Neuerung bei den Concurrency Utilities ist die TransferQueue. Dabei handelt es sich um eine Kombination aus einer normalen BlockingQueue und einer SynchronousQueue. Bei Bedarf kann der Producer warten, bis ein Consumer das neue Element abholt (wie bei der SynchronousQueue); alternativ kann er das Element einfach in die Queue legen, ohne auf einen Abholer zu warten (wie bei der normalen BlockingQueue).

Kommentare

Schreibe einen Kommentar

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