in core/src/main/java/com/taobao/arthas/core/util/ThreadUtil.java [99:159]
public static BlockingLockInfo findMostBlockingLock() {
ThreadInfo[] infos = threadMXBean.dumpAllThreads(threadMXBean.isObjectMonitorUsageSupported(),
threadMXBean.isSynchronizerUsageSupported());
// a map of <LockInfo.getIdentityHashCode, number of thread blocking on this>
Map<Integer, Integer> blockCountPerLock = new HashMap<Integer, Integer>();
// a map of <LockInfo.getIdentityHashCode, the thread info that holding this lock
Map<Integer, ThreadInfo> ownerThreadPerLock = new HashMap<Integer, ThreadInfo>();
for (ThreadInfo info: infos) {
if (info == null) {
continue;
}
LockInfo lockInfo = info.getLockInfo();
if (lockInfo != null) {
// the current thread is blocked waiting on some condition
if (blockCountPerLock.get(lockInfo.getIdentityHashCode()) == null) {
blockCountPerLock.put(lockInfo.getIdentityHashCode(), 0);
}
int blockedCount = blockCountPerLock.get(lockInfo.getIdentityHashCode());
blockCountPerLock.put(lockInfo.getIdentityHashCode(), blockedCount + 1);
}
for (MonitorInfo monitorInfo: info.getLockedMonitors()) {
// the object monitor currently held by this thread
if (ownerThreadPerLock.get(monitorInfo.getIdentityHashCode()) == null) {
ownerThreadPerLock.put(monitorInfo.getIdentityHashCode(), info);
}
}
for (LockInfo lockedSync: info.getLockedSynchronizers()) {
// the ownable synchronizer currently held by this thread
if (ownerThreadPerLock.get(lockedSync.getIdentityHashCode()) == null) {
ownerThreadPerLock.put(lockedSync.getIdentityHashCode(), info);
}
}
}
// find the thread that is holding the lock that blocking the largest number of threads.
int mostBlockingLock = 0; // System.identityHashCode(null) == 0
int maxBlockingCount = 0;
for (Map.Entry<Integer, Integer> entry: blockCountPerLock.entrySet()) {
if (entry.getValue() > maxBlockingCount && ownerThreadPerLock.get(entry.getKey()) != null) {
// the lock is explicitly held by anther thread.
maxBlockingCount = entry.getValue();
mostBlockingLock = entry.getKey();
}
}
if (mostBlockingLock == 0) {
// nothing found
return EMPTY_INFO;
}
BlockingLockInfo blockingLockInfo = new BlockingLockInfo();
blockingLockInfo.setThreadInfo(ownerThreadPerLock.get(mostBlockingLock));
blockingLockInfo.setLockIdentityHashCode(mostBlockingLock);
blockingLockInfo.setBlockingThreadCount(blockCountPerLock.get(mostBlockingLock));
return blockingLockInfo;
}