JEP 259: Verarbeitung von Stackframes und die Klasse „StackWalker“

© Shutterstock.com / Profit_Image
Das kürzlich erschienene Java 9 besteht aus mehr als nur Modulen und dem Projekt Jigsaw. Über 90 sogenannte JEPs (JDK Enhancement Proposals) sind Teil von Version 9 des Java Development Kits. Im sechsten Teil seiner Serie zu Java 9 stellt Michael Inden, Oracle-zertifizierter Java-Entwickler, weitere mit JDK 9 eingeführte API-Erweiterungen vor, die im JEP 259 zusammengefasst sind.
Die vorliegende Artikelserie zu Java 9 setzt sich aus Texten von Michael Indens Buch „Java 9 – Die Neuerungen“ zusammen, das beim dpunkt.verlag erschienen ist.
PS: Verpassen Sie nicht unsere Infografik zu Project Jigsaw!
Nachdem wir im ersten Teil dieser Blog-Serie diverse kleinere Änderungen in der Syntax der Sprache Java kennengelernt haben, schauten wir uns im zweiten Teil einige relevante Erweiterungen im JDK an, konkreter: im Process-API und den Collection-Factory-Methoden. Im dritten Teil ging es anschließend um die Ergänzungen im Stream-API, im vierten Teil bespricht Michael Inden die Erweiterungen in Optional<T>
. Im fünften Teil der Artikelserie stehen die Erweiterungen der Java-Klasse LocalDate
im Fokus, in Teil 6 geht es nun um die Verarbeitung von Stackframes und die Klasse StackWalker
.
Stackframes & die Klasse „StaackWalker“
Für Auswertungen und Debuggingzwecke kann zum Teil der Zugriff auf den Stacktrace hilfreich sein. Vor JDK 9 gab es als gewöhnungsbedürftige Möglichkeit das Auslösen und Fangen einer Exception und das Schreiben des Stacktrace in einen java.io.OutputStream
, den man im Anschluss auswerten konnte. JDK 9 macht das Entwicklerleben leichter und bietet nun Zugriff auf den Stacktrace über die Klasse java.lang.StackWalker
und das Stream-API. Die mit JDK 9 neu eingeführte Klasse StackWalker
erlaubt eine Verarbeitung von Stackframes. Als Beispiel implementieren wie eine Methode provideStackframesJdk9()
. Diese realisiert das Durchlaufen der Stackframes. Dabei findet eine Filterung und eine Abbildung von StackFrame
auf Klassen- und Methodenname sowie Zeilennummern statt:
private static List<String> provideStackframesJdk9() { return StackWalker.getInstance().walk(extractClassMethodAndLineNumber()); } private static Function<Stream<StackFrame>, List<String>> extractClassMethodAndLineNumber() { final Predicate<String> isJdk9Example = name -> name.containsWith("jdk9example"); return stream -> stream.map(frame -> frame.getClassName() + "/" + frame.getMethodName() + "@line:" + frame.getLineNumber()) .filter(isJdk9Example) .collect(Collectors.toList()); }
Im obigen Listing nutzen wir die Methode walk()
, die die übergebene Function<T,R>
auf einen Stream von StackFrames
anwendet und dabei am Anfang des Stacks beginnt, der der aufrufenden Methode entspricht (also derjenigen, die walk()
aufruft).
Fazit
Das in JDK 9 eingeführte StackWalker
-API erleichtert die Auswertung und Verarbeitung von Stackframes und spielt zudem gut mit dem Stream-API zusammen. Vor allem für Entwicklungen von Tools oder für Debuggingzwecke kann das mitunter hilfreich sein. Ansonsten wird man eher selten Zugriff auf den Stacktrace benötigen.
Erweiterungen in der Klasse InputStream
Die Verarbeitung von InputStreams
und OutputStreams
bietet bis einschließlich JDK 8 mitunter nicht den Komfort, den man erwarten würde. Mit JDK 9 wurde die Situation verbessert und die Klasse InputStream um folgende zwei Methoden erweitert:
readAllBytes()
– Liest alle Bytes aus dem Stream.transferTo(OutputStream)
– Diese Methode erlaubt das Kopieren von Daten von einemInputStream
in einenOutputStream
.
Anhand eines Beispiels wollen wir die beiden Methoden im Einsatz erleben:
public static void main(final String[] args) throws IOException { final byte[] buffer = { 72, 65, 76, 76, 79 }; // Liest alle Bytes in einem Rutsch final byte[] result = new ByteArrayInputStream(buffer).readAllBytes(); System.out.println(Arrays.toString(result)); // Überträgt Daten direkt aus einem InputStream in einen OutputStream new ByteArrayInputStream(buffer).transferTo(System.out); }
Startet man das obige Programm, so werden die Daten aus dem byte[]
namens buffer
eingelesen und später auf die Konsole transferiert. Dabei kommt es zu folgenden Ausgaben:
[72, 65, 76, 76, 79] HALLO
Vielleicht fragen Sie sich, wieso ein byte
als Zeichen ausgegeben wird. Das liegt daran,
dass die Zeichen den ASCII-Werten der Buchstaben entsprechen.
Fazit
Die Erweiterung in der Klasse InputStream
ist zwar nur klein, aber fein. Die Methode readAllBytes()
zum Einlesen der Daten eines Streams ist viel angenehmer in der Handhabung, als alle Bytes in einer Schleife einlesen zu müssen. Auch das Kopieren von Daten ist mithilfe von transferTo(OutputStream)
nun mit einem Einzeiler zu lösen.

Michael Indens Buch bietet einen fundierten Einstieg in Java 9 sowie einen Überblick über die umfangreichen Neuerungen in der aktuellen Version. Damit eignet sich das Buch für all jene, die ihr Java-Wissen aktualisieren wollen. Dabei helfen eine Vielzahl an Übungen, um die einzelnen Themengebiete zu vertiefen und besser zu verstehen.
Neben Änderungen an der Sprache bilden auch die Erweiterungen in diversen APIs einen Schwerpunkt. Fehlen darf hier natürlich auch nicht ein Kapitel über die fundamentalste Änderung in Java 9: Project Jigsaw. Auch fortgeschrittenere Themen wie Services und die Migration bestehender Applikationen werden besprochen. Da Java 9 auch einige Auswirkungen auf Build Tools und IDEs mit sich bringt, gibt ein Kapitel einen Überblick über den derzeitigen Stand zum Tooling rund um die neue Java-Version.
Hinterlasse einen Kommentar