Taking ThreadDump from Java Code

Copied from HERE with some code modification.

import java.io.ByteArrayOutputStream;
import java.io.UnsupportedEncodingException;
import java.lang.management.ManagementFactory;
import java.util.Scanner;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.LongAdder;

public class StackTraceUtils {
	private static final char PID_SEPERATOR = '@';
	private static String pathToJStack = "jstack";

	private static String acquirePid()
		String mxName = ManagementFactory.getRuntimeMXBean().getName();

		int index = mxName.indexOf(PID_SEPERATOR);

		String result;

		if (index != -1) {
			result = mxName.substring(0, index);
		} else {
			throw new IllegalStateException("Could not acquire pid using " + mxName);

		return result;

	public static String executeJstack()
		ProcessInterface pi = new ProcessInterface();

		int exitCode;

		ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();

		try {
			exitCode = pi.run(new String[] { pathToJStack, "-l", acquirePid(),}, byteArrayOutputStream);
		} catch (Exception e) {
			throw new IllegalStateException("Error invoking jstack", e);

		if (exitCode != 0) {
			throw new IllegalStateException("Bad jstack exit code " + exitCode);

		try {
			String str = new String(byteArrayOutputStream.toByteArray(), "UTF-8");
			return str;
		} catch (UnsupportedEncodingException e) {
			throw new RuntimeException(e);


	public static void main(String[] args) {

		final String s = executeJstack();
		System.out.println("s = " + s);

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

public class ProcessInterface
	private final Map<String, String> addModifyEnv;
	private final Set<String> removeEnv;
	static class StreamGobbler extends Thread
		private static int gobblerNumber = 0;
		private final InputStream is;
		private final OutputStream os;
		private static synchronized int getNextGobblerNumber()
			return gobblerNumber++;
		public StreamGobbler(InputStream is, OutputStream os)
			super("StreamGobblerThread-" + getNextGobblerNumber());
			this.is = is;
			this.os = os;
		public void run()
				OutputStreamWriter osw = new OutputStreamWriter(os);
				BufferedWriter bw = new BufferedWriter(osw);
				InputStreamReader isr = new InputStreamReader(is);
				BufferedReader br = new BufferedReader(isr);
				String line = null;
				while ((line = br.readLine()) != null)
			catch (IOException ioe)
				throw new IllegalStateException(ioe);
	public ProcessInterface()
		this.addModifyEnv = new HashMap<String, String>();
		this.removeEnv = new HashSet<String>();
	public void removeEnv(String name)
		if (addModifyEnv.containsKey(name))
	public void addEnv(String name, String value)
		if (removeEnv.contains(name))
		addModifyEnv.put(name, value);
	public int run(String[] command) throws InterruptedException, IOException
		return run(command, null, null, null);
	public int run(String[] command, File workingDir) throws InterruptedException, IOException
		return run(command, null, null, workingDir);
	public int run(String[] command, OutputStream os) throws InterruptedException, IOException
		return run(command, os, os, null);
	public int run(String[] command, OutputStream os, File workingDir) throws InterruptedException, IOException
		return run(command, os, os, workingDir);
	public int run(String[] command, OutputStream std, OutputStream err, File workingDir)
			throws InterruptedException, IOException
		StringBuilder sb = new StringBuilder();
		for (String s : command)
			sb.append(" ");
		ProcessBuilder builder = new ProcessBuilder();
		if (workingDir != null)
		Map<String, String> env = builder.environment();
		for (String name : removeEnv)
		for (Entry<String, String> entry : addModifyEnv.entrySet())
			env.put(entry.getKey(), entry.getValue());
		Process process = builder.start();
		OutputStream outStream = ((std == null) ? System.out : std);
		OutputStream errStream = ((err == null) ? System.err : err);
		StreamGobbler outputGobbler = new StreamGobbler(process.getInputStream(), outStream);
		StreamGobbler errorGobbler = new StreamGobbler(process.getErrorStream(), errStream);
		int exitVal = process.waitFor();
		return exitVal;

This can be very helpful, for example in a code block you suspect there is a deadlock, for Example timeout from connection pool , you can log the stacktrace so you can come back later and run a ThreadDump analysis tool on it. Add it to your code before the Operations guy restart your problematic server and report an issue in your name !

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s