---
title: 'StackWalker and Stack-Walking API'
url: 'https://tutego.de/blog/javainsel/2017/02/stackwalker-and-stack-walking-api'
markdown: 'https://tutego.de/blog/javainsel/2017/02/stackwalker-and-stack-walking-api.md'
date: '2017-02-25'
description: 'Der Stack-Trace, den Java über die StackTraceElement bietet, ist relativ arm an Informationen, und die Standardausgabe über die Throwable-Methode printStackTrace(…) ist unübersichtlich. Aus Performance-Gründen können sogar Einträge fehlen, so dokumentiert es die Javadoc an der Methode: Some virtua…'
taxonomy:
  category:
    - Allgemein
    - Insel
    - 'Java 9'
---

# StackWalker and Stack-Walking API

![Illustration einer tropischen Insel mit Palmen und einem hohen Berg](https://tutego.de/blog/javainsel/user/themes/tutego/images/insel-cover.jpg)# Java Blog für Programmierer

[Java Blog für Programmierer](https://tutego.de/blog/javainsel/)

## StackWalker and Stack-Walking API

25.02.2017 · [Christian Ullenboom](https://tutego.de/blog/javainsel/author/admin/)

Der Stack-Trace, den Java über die StackTraceElement bietet, ist relativ arm an Informationen, und die Standardausgabe über die `Throwable`-Methode `printStackTrace(…)` ist unübersichtlich. Aus Performance-Gründen können sogar Einträge fehlen, so dokumentiert es die Javadoc an der Methode:

> Some virtual machines may, under some circumstances, omit one or more stack frames from the stack trace. In the extreme case, a virtual machine that has no stack trace information concerning this thread is permitted to return a zero-length array from this method.

Zudem fehlen spannende Informationen wie Zeitpunkte, und ein `Thread.getAllStackTraces()` ist bei vielen Threads und tiefen Aufrufhierarchien sehr langsam. Summa summarum: Ein guter Debugger oder ein Analysetool mit Zugriff auf die JVM-Eigenschaften ist für die ernsthafte Entwicklung unumgänglich.

In Java 9 hat Oracle die “JEP 259: Stack-Walking API” umgesetzt. Ein `java.lang.StackWalker` wandert die Aufrufhierarchie ab und repräsentiert die Aufrufhierarchie als StackFrame-Objekte von dort, wo der Stack generiert wurde, nach unten zur Aufrufstelle. Es gibt mehrere überladenen statische `getInstance(…)`-Methoden, die einen StackWalker generieren. Wir können dann mit

- void `forEach`(`Consumer`<? super StackFrame> action) oder
- <T> T walk(`Function`<? super `Stream`<StackFrame>, ? extends T> function)

über die StackFrames laufen.

Beispiel:

```java
public static void showTrace() {

  List frames =

    StackWalker.getInstance( Option.RETAIN_CLASS_REFERENCE )

               .walk( stream  -> stream.collect( Collectors.toList() ) );

  for ( StackFrame stackFrame : frames )

    System.out.println( stackFrame );

}
```

Da alle Informationen zu liefern die Geschwindigkeit senkt, und vielleicht unnötig viel Arbeit verursacht, deklariert die Aufzählung StackWalker.Option die Konstanten RETAIN\_CLASS\_REFERENCE, SHOW\_HIDDEN\_FRAMES, SHOW\_REFLECT\_FRAMES für unterschiedliche Vollständigkeit der Informationen. Die Aufzählungen sind ein Argument für `getInstance(…)`. Um die `Class`-Objekte über `getDeclaringClass()` abrufen zu können, muss `getInstance(…)` mit der Option.RETAIN\_CLASS\_REFERENCE gesetzt sein.

Beispiel: Die `forEach(…)`-Methode eines Streams konsumiert einen `Consumer` auf jedem Element. Finde heraus, ob unsere `Consumer`-Methode `accept(…)` indirekt von einer Klasse aus dem Paket `java.util.concurrent` aufgerufen wurde:

```java
Consumer walkStack = String -> {

  StackWalker.getInstance( Option.RETAIN_CLASS_REFERENCE )

        .walk( stream -> stream.map( StackFrame::getDeclaringClass )

                               .map( Class::getPackageName )

                               .filter( s -> s.startsWith( "java.util.concurrent" ) )

                               .findFirst() )

                               .ifPresentOrElse( e -> System.out.println( "Durch j.u.c gelaufen" ),

                                                 () -> System.out.println( "Nicht durch j.u.c gelaufen" ) );

};

Stream.of( "Hallo" ).forEach( walkStack );            // Nicht durch j.u.c gelaufen

Stream.of( "Hallo" ).parallel().forEach( walkStack ); // Durch j.u.c gelaufen
```

Kategorien: [Allgemein](https://tutego.de/blog/javainsel/category/allgemein/), [Insel](https://tutego.de/blog/javainsel/category/insel/), [Java 9](https://tutego.de/blog/javainsel/category/java-9/)

[← Alle Beiträge](https://tutego.de/blog/javainsel/)

---

## Navigation

- Previous: [ProcessHandle und Prozess-IDs](https://tutego.de/blog/javainsel/2017/02/processhandle-und-prozess-ids.md)
- Next: [Private Schnittstellenmethoden](https://tutego.de/blog/javainsel/2017/02/private-schnittstellenmethoden.md)
