最近在做openapm 监控相关的项目,其中涉及到破析线程dump的功能。其中有2个方案。
第一个方案是指令获取: jstack -l pid。
第二种方案是在程序里面开一个线程获取数据。代码如下
public class Runthread {
public static void main(String[] args) {
// 线程1
new Thread() {
@Override
public void run() {
System.out.println("这是线程1的run1111111111");
}
}.start();
// 线程2
new Thread() {
@Override
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("这是线程2的run222222222");
}
}.start();
ThreadMXBean b = ManagementFactory.getThreadMXBean();
List<ThreadInfo> threadInfoList = Arrays
.asList(b.dumpAllThreads(b.isObjectMonitorUsageSupported(), b.isSynchronizerUsageSupported()));
for (ThreadInfo info : threadInfoList) {
TThreadDump dump = new TThreadDump();
dump.setThreadName(info.getThreadName());
dump.setThreadId(info.getThreadId());
dump.setBlockedTime(info.getBlockedTime());
dump.setBlockedCount(info.getBlockedCount());
dump.setWaitedTime(info.getWaitedTime());
dump.setWaitedCount(info.getWaitedCount());
dump.setLockName(info.getLockName());
dump.setLockOwnerId(info.getLockOwnerId());
dump.setLockOwnerName(info.getLockOwnerName());
dump.setInNative(info.isInNative());
dump.setSuspended(info.isSuspended());
dump.setThreadState(getThreadState(info));
StackTraceElement[] stackTraceElements = info.getStackTrace();
for (StackTraceElement each : stackTraceElements) {
dump.addToStackTrace(each.toString());
}
MonitorInfo[] monitorInfos = info.getLockedMonitors();
for (MonitorInfo each : monitorInfos) {
TMonitorInfo tMonitorInfo = new TMonitorInfo();
tMonitorInfo.setStackDepth(each.getLockedStackDepth());
tMonitorInfo.setStackFrame(each.getLockedStackFrame().toString());
dump.addToLockedMonitors(tMonitorInfo);
}
LockInfo[] lockInfos = info.getLockedSynchronizers();
for (LockInfo lockInfo : lockInfos) {
dump.addToLockedSynchronizers(lockInfo.toString());
}
System.out.println(dump.toString());
}
System.err.println("-----------------------------");
}
private static TThreadState getThreadState(ThreadInfo info) {
String stateName = info.getThreadState().name();
for (TThreadState state : TThreadState.values()) {
if (state.name().equalsIgnoreCase(stateName)) {
return state;
}
}
return null;
}
}
其中:class TMonitorInfo: private int stackDepth; // required
private String stackFrame; // required
class TThreadDump: private String threadName; // required
private long threadId; // required
private long blockedTime; // required
private long blockedCount; // required
private long waitedTime; // required
private long waitedCount; // required
private String lockName; // required
private long lockOwnerId; // required
private String lockOwnerName; // required
private boolean inNative; // required
private boolean suspended; // required
private TThreadState threadState; // required
private List<String> stackTrace; // required
private List<TMonitorInfo> lockedMonitors; // required
private List<String> lockedSynchronizers; // required
enum TThreadState:
NEW(0),
RUNNABLE(1),
BLOCKED(2),
WAITING(3),
TIMED_WAITING(4),
TERMINATED(5),
UNKNOWN(6);
private final int value;
private TThreadState(int value) {
this.value = value;
}
/**
* Get the integer value of this enum value, as defined in the Thrift IDL.
*/
public int getValue() {
return value;
}
/**
* Find a the enum type by its integer value, as defined in the Thrift IDL.
* @return null if the value is not found.
*/
public static TThreadState findByValue(int value) {
switch (value) {
case 0:
return NEW;
case 1:
return RUNNABLE;
case 2:
return BLOCKED;
case 3:
return WAITING;
case 4:
return TIMED_WAITING;
case 5:
return TERMINATED;
case 6:
return UNKNOWN;
default:
return null;
}
}