In this short article, we will learn how to collect a Thread Dump in a Spring Boot application which exposes the Actuator API.
Thread Dump Overview
Java has mechanisms to analyse the state of all the threads of an application at a given time: Thread dumps.
Thread dumps are files that you can generate by various commands or applications. The easiest way to get them is to use a command included in the Java Development Kit installation: jstack -l {PID} where {PID} is the id of the Java process to be monitored.
The Spring Boot application itself is a java application, so you will need to call the command with the id of the Spring Boot process.
Thread dumps are text files so they can be read quite easily without any further aids. However, the threads involved can be numerous and reading and cross-referencing information of potential problems can be facilitated by so-called Thread Dump Analyzers (TDAs), tools that can show the dump information in a clearer way (usually using graphs). Examples of such tools are fastThread, IBM Thread and Monitor Dump Analyze for Java, irockel TDA.
Let’s see how to capture a Thread Dump using Spring Boot actuator REST API, which allows to capture metrics and data remotely.
Requirements
We recommend to check the following tutorial for an introduction on Spring Boot Actuator: Configuring Spring Boot Actuator
Firstly, you need to expose the thread dump in the list of management endpoints. Include the following in the file application.properties:
management.endpoints.web.exposure.include=threaddump
On the other hand, if you are using a YAML file for your configuration, include the following:
management: endpoints: web: exposure: include: "threaddump"
Next, start the Spring Boot application and find the ProcessId of it:
To capture the Thread Dump, you can
curl 'http://localhost:8080/actuator/threaddump'
By default, the Actuator will return a Response in JSON format. This is not valid for most of the tools to analyze Thread Dumps. To capture the Thread Dump in a text format you can just use:
curl 'http://localhost:8080/actuator/threaddump' -i -X GET -H 'Accept: text/plain'
You will see on the Console the Thread Dump output:
. . . . . . . . . "http-nio-8080-Acceptor" - Thread t@30 java.lang.Thread.State: RUNNABLE at java.base@11/sun.nio.ch.ServerSocketChannelImpl.accept0(Native Method) at java.base@11/sun.nio.ch.ServerSocketChannelImpl.accept(ServerSocketChannelImpl.java:533) at java.base@11/sun.nio.ch.ServerSocketChannelImpl.accept(ServerSocketChannelImpl.java:285) at app//org.apache.tomcat.util.net.NioEndpoint.serverSocketAccept(NioEndpoint.java:546) at app//org.apache.tomcat.util.net.NioEndpoint.serverSocketAccept(NioEndpoint.java:79) at app//org.apache.tomcat.util.net.Acceptor.run(Acceptor.java:129) at java.base@11/java.lang.Thread.run(Thread.java:834) Locked ownable synchronizers: - Locked <f9a76c8> (a java.util.concurrent.locks.ReentrantLock$NonfairSync) "DestroyJavaVM" - Thread t@31 java.lang.Thread.State: RUNNABLE Locked ownable synchronizers: - None
Further reading: If you want to learn more about Thread Dump Analysis check this tutorial: How to analyze a Thread dump
Found the article helpful? if so please follow us on Socials