blob: 405b96c3a55656754894390f4d6cc5f16d69dbd6 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2019 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.osgi.framework.util;
import java.lang.management.LockInfo;
import java.lang.management.ManagementFactory;
import java.lang.management.MonitorInfo;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
public class ThreadInfoReport extends RuntimeException {
private static final long serialVersionUID = 1L;
public ThreadInfoReport(String failedMonitor) {
super(getThreadDump(failedMonitor));
}
public static String getThreadDump(String failedMonitor) {
long currentId = Thread.currentThread().getId();
ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
StringBuilder dump = new StringBuilder("Thread dump"); //$NON-NLS-1$
ThreadInfo[] infos = threadMXBean.dumpAllThreads(threadMXBean.isObjectMonitorUsageSupported(), threadMXBean.isSynchronizerUsageSupported());
for (ThreadInfo info : infos) {
dumpThreadIDNameState(info, dump);
dumpLockInfo(currentId, failedMonitor, info, dump);
dumpStackTrace(info, dump);
}
return dump.toString();
}
private static void dumpThreadIDNameState(ThreadInfo info, StringBuilder dump) {
dump.append('\n').append('\n');
dump.append("ThreadId: ").append(info.getThreadId()); //$NON-NLS-1$
dump.append(" ThreadName: ").append(info.getThreadName()); //$NON-NLS-1$
dump.append(" ThreadState: ").append(info.getThreadState()); //$NON-NLS-1$
}
private static void dumpLockInfo(long currentId, String failedMonitor, ThreadInfo info, StringBuilder dump) {
dump.append('\n');
dump.append(" Blocked On: "); //$NON-NLS-1$
LockInfo blockedOn = info.getLockInfo();
if (blockedOn == null) {
if (currentId == info.getThreadId() && failedMonitor != null) {
dump.append(failedMonitor);
} else {
dump.append("none"); //$NON-NLS-1$
}
} else {
dump.append(blockedOn.toString());
dump.append(" LockOwnerId: ").append(info.getLockOwnerId()); //$NON-NLS-1$
dump.append(" LockOwnerName: ").append(info.getLockOwnerName()); //$NON-NLS-1$
}
dump.append('\n');
dump.append(" Synchronizers Locked: "); //$NON-NLS-1$
LockInfo[] synchronizers = info.getLockedSynchronizers();
if (synchronizers.length == 0) {
dump.append("none"); //$NON-NLS-1$
} else {
for (LockInfo sync : synchronizers) {
dump.append('\n');
dump.append(" ").append(sync.toString()); //$NON-NLS-1$
}
}
dump.append('\n');
dump.append(" Monitors Locked: "); //$NON-NLS-1$
MonitorInfo[] monitors = info.getLockedMonitors();
if (monitors.length == 0) {
dump.append("none"); //$NON-NLS-1$
}
for (MonitorInfo monitor : monitors) {
dump.append('\n');
dump.append(" ").append(monitor.toString()); //$NON-NLS-1$
}
dump.append('\n');
}
private static void dumpStackTrace(ThreadInfo info, StringBuilder dump) {
dump.append(" Stack Trace: "); //$NON-NLS-1$
for (StackTraceElement e : info.getStackTrace()) {
dump.append('\n').append(" ").append(e); //$NON-NLS-1$
}
}
}