Thread dump in java provides all the state of currently existing threads in the java process. A thread dump is useful for troubleshooting because it shows the thread’s activity. A thread’s stack trace displays the thread’s current state, as well as the thread’s stack status and details. Thread dumps are used to diagnose deadlocks, memory issues, hanging threads, thread response, thread cpu usage, and other system thread issues.

Spring Boot supports to get a thread dump from an out-of-the-box implementation. In the spring boot application, the spring boot actuator helps in the generation of the thread dump. In spring boot, the /threaddump actuator endpoint is used to obtain a thread dump.



1. add dependency in pom.xml

Spring-boot-starter-actuator and spring-boot-starter-web are two dependents of the spring boot actuator. All of the actuator endpoints, including the thread dump, are contained in the spring-boot-starter-actuator. The thread dump content is exposed in json format in the web browser thanks to the spring-boot-starter-web dependency. The thread dump will be displayed in json format.

pom.xml

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-actuator</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>


2. Expose the thread dump endpoints

The spring boot actuator’s thread dump actuator endpoint is enabled by default. The /threaddump endpoint isn’t exposed. The following configuration should be used to expose the /threaddump url. All or a subset of endpoints can be exposed using a spring boot actuator. In a production environment, it is recommended to only expose the thread dump endpoint for security reasons. Otherwise, all of the actuator endpoints can be exposed.

application.properties – expose all endpoints

management.endpoints.web.exposure.include=*

application.properties – expose thread dump endpoints

management.endpoints.web.exposure.include=threaddump


3. Sample thread to test

A rest controller class is demonstrated in the example below. A rest api will be included in the rest controller class, which will generate a thread and run it every 5 seconds. We’ll start the thread and check its details, such as the thread status, thread stack details, and thread details, among other things using the thread dump.

TestController.java

package com.yawintutor;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TestController {

	@RequestMapping(value = "/hello", method = RequestMethod.GET)
	public String testHello() {
		System.out.println("Executing testHello Method");
		new Thread("test") {
			public void run()  {
				System.out.println("running");
				try {
					Thread.sleep(5000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		} .start();
		return "TEST OK";
	}

}


4. How to get thread dump

The rest api should be used to start the thread. The url http://localhost:8080/hello invokes the rest api and creates a thread named “test” in the rest controller. The thread will run every 5 seconds.

http://localhost:8080/hello

The spring boot actuator endpoints can be used to get a thread dump. The url http://localhost:8080/actuator will display a list of all the spring boot endpoints. The thread dump in json format in the spring boot application can be viewed at http://localhost:8080/actuator/threaddump.

http://localhost:8080/actuator/threaddump


5. Threaddump details

The thread dump information of the invoked thread in the spring boot application are shown in the following example. The threaddump command displays the information in json format. The following are the sample details.

...............
    {
      "threadName": "test",
      "threadId": 51,
      "blockedTime": -1,
      "blockedCount": 0,
      "waitedTime": -1,
      "waitedCount": 1,
      "lockName": null,
      "lockOwnerId": -1,
      "lockOwnerName": null,
      "daemon": true,
      "inNative": false,
      "suspended": false,
      "threadState": "TIMED_WAITING",
      "priority": 5,
      "stackTrace": [
        {
          "classLoaderName": null,
          "moduleName": "java.base",
          "moduleVersion": "11.0.9",
          "methodName": "sleep",
          "fileName": "Thread.java",
          "lineNumber": -2,
          "className": "java.lang.Thread",
          "nativeMethod": true
        },
        {
          "classLoaderName": "app",
          "moduleName": null,
          "moduleVersion": null,
          "methodName": "run",
          "fileName": "TestController.java",
          "lineNumber": 17,
          "className": "com.yawintutor.TestController$1",
          "nativeMethod": false
        }
      ],
      "lockedMonitors": [],
      "lockedSynchronizers": [],
      "lockInfo": null
    },
............
............



Leave a Reply