2

I have a threaddump and in this threaddump each thread is displayed in a format as below:

"isThreadCpuTimeSupported": "true",
"getLockOwnerName": null,
"isSuspended": "false",
"stacktrace": "java.base@11.0.5/java.net.PlainSocketImpl.accept0(Native 
"cpuTime": "36359.375",
"userTime": "25828.125",
"threadState": "RUNNABLE",
"id": "1",
"lockName": null,
"threadName": "main",
"isNative": "true"

My requirement is to get the threadGroup of each thread, How can I get that? Do i have to add them in a thread group first? How do I know if they are already a part of threadgroup? On website Fastthread.io when I upload my thread dump it automatically finds the thread group, how does it do that?

On server side I am doing something like this to get threaddump:

ThreadMXBean tmbean = ManagementFactory.getThreadMXBean();
List<HashMap> list = new ArrayList<>();
long[] tids;
ThreadInfo[] tinfos;
tids = tmbean.getAllThreadIds();
tinfos = tmbean.getThreadInfo(tids, Integer.MAX_VALUE);

for (ThreadInfo ti : tinfos) {
    try {
        list.add( printThreadInfo(ti,tmbean,response ));
    } catch (IOException ex) {
        _logger.error("could not call printThreadInfo",ex);
    }
}
...
...

and for each ti

map.put("threadName", ti.getThreadName());
skr
  • 1,700
  • 1
  • 15
  • 39

2 Answers2

3

thread group information is not part of ThreadInfo see https://bugs.openjdk.java.net/browse/JDK-8023908

you can get it from the thread object itself t.getThreadGroup()

Fastthread.io probably using the name since every thread pool used to give a name with a pattern so they can group threads with a similar name as a group(this groups probably doesn't have the features of the object ThreadGroup as in https://docs.oracle.com/javase/7/docs/api/java/lang/ThreadGroup.html)

as they said(fastthread using the name for group threads): https://www.perfmatrix.com/fastthread-thread-dump-analyzer/ enter image description here

Sarel Foyerlicht
  • 907
  • 6
  • 11
3

As mentioned by Sarel Foyerlicht, ThreadInfo does not have information on ThreadGroup. We can make use of Thread#getThreadGroup() to get the group information, by following steps:

  1. Get the top ThreadGroup, refer to answer of reference [1]
  2. Iterate the Thread and the sub ThreadGroup recursively to get a mapping between Thread and corresponding ThreadGroup, see reference [2] for relation between Thread and ThreadGroup

The following program demonstrates the above steps.


import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import java.util.HashMap;
import java.util.Map;

public class ThreadDumpWithGroup {
    public static void main(String args[]) {
        ThreadGroup top = getTopThreadGroup();
        Map<Long, String> threadIdToThreadGroupNameMap = new HashMap<>();
        putThreadIdToThreadGroupNameMap(top, threadIdToThreadGroupNameMap);
        ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
        long[] threadIds;
        ThreadInfo[] threadInfos;
        threadIds = threadBean.getAllThreadIds();
        threadInfos = threadBean.getThreadInfo(threadIds, Integer.MAX_VALUE);
        for (ThreadInfo threadInfo : threadInfos) {
            // May still be null as there may be new thread after constructing the map.
            String threadGroupName = threadIdToThreadGroupNameMap.get(threadInfo.getThreadId());
            String threadName = threadInfo.getThreadName();
            long threadId = threadInfo.getThreadId();
            System.out.println(
                    String.format("Group:%s, Thread Name:%s, Thread Id:%d", threadGroupName, threadName, threadId));
        }
    }

    /**
     * Result maybe inaccurate, see
     * {@link java.lang.ThreadGroup#enumerate(Thread[], boolean) enumerate}
     * {@link java.lang.ThreadGroup#enumerate(ThreadGroup[], boolean) enumerate}
     **/
    private static void putThreadIdToThreadGroupNameMap(ThreadGroup group,
            Map<Long, String> threadIdToThreadGroupNameMap) {
        Thread[] threads = new Thread[group.activeCount()];
        group.enumerate(threads, false);
        for (Thread thread : threads) {
            if (thread == null) {
                continue;
            }
            threadIdToThreadGroupNameMap.put(thread.getId(), group.getName());
        }

        ThreadGroup[] subGroups = new ThreadGroup[group.activeGroupCount()];
        group.enumerate(subGroups, false);
        for (ThreadGroup subGroup : subGroups) {
            putThreadIdToThreadGroupNameMap(subGroup, threadIdToThreadGroupNameMap);
        }
    }

    private static ThreadGroup getTopThreadGroup() {
        ThreadGroup top = Thread.currentThread().getThreadGroup();
        ThreadGroup parent;
        do {
            parent = top.getParent();
            if (parent != null) {
                top = parent;
            }
        } while (parent != null);
        return top;
    }
}

References
Get a list of all threads currently running in Java
Java 101: Understanding Java threads, Part 4: Thread groups, volatility, and thread-local variables
Java Doc Thread Group

samabcde
  • 6,988
  • 2
  • 25
  • 41