/*
* Copyright 2014 NAVER Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.navercorp.pinpoint.common.util;
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* @author emeroad
*/
public final class ThreadMXBeanUtils {
private static final ThreadMXBean THREAD_MX_BEAN = ManagementFactory.getThreadMXBean();
private static final boolean OBJECT_MONITOR_USAGE_SUPPORT;
private static final boolean SYNCHRONIZER_USAGE_SUPPORT;
// check support -> getWaitedTime(), getBlockedTime()
private static final boolean CONTENTION_MONITORING_SUPPORT;
private static final int DEFAULT_STACK_TRACE_MAX_DEPTH = 32;
private ThreadMXBeanUtils() {
}
static {
OBJECT_MONITOR_USAGE_SUPPORT = THREAD_MX_BEAN.isObjectMonitorUsageSupported();
SYNCHRONIZER_USAGE_SUPPORT = THREAD_MX_BEAN.isSynchronizerUsageSupported();
CONTENTION_MONITORING_SUPPORT = THREAD_MX_BEAN.isThreadContentionMonitoringSupported();
}
// for test
static String getOption() {
final StringBuilder builder = new StringBuilder();
builder.append("ThreadMXBean SupportOption:{OBJECT_MONITOR_USAGE_SUPPORT=");
builder.append(OBJECT_MONITOR_USAGE_SUPPORT);
builder.append("}, {SYNCHRONIZER_USAGE_SUPPORT=");
builder.append(SYNCHRONIZER_USAGE_SUPPORT);
builder.append("}, {CONTENTION_MONITORING_SUPPORT=");
builder.append(CONTENTION_MONITORING_SUPPORT);
builder.append('}');
return builder.toString();
}
public static ThreadInfo[] dumpAllThread() {
// try {
return THREAD_MX_BEAN.dumpAllThreads(OBJECT_MONITOR_USAGE_SUPPORT, SYNCHRONIZER_USAGE_SUPPORT);
// ?? handle exception
// } catch (java.lang.SecurityException se) {
// log??
// return new ThreadInfo[]{};
// } catch (java.lang.UnsupportedOperationException ue) {
// log??
// return new ThreadInfo[]{};
// }
}
public static ThreadInfo findThread(Thread thread) {
return findThread(thread.getId());
}
public static ThreadInfo findThread(Thread thread, int stackTraceMaxDepth) {
return findThread(thread.getId(), stackTraceMaxDepth);
}
public static ThreadInfo findThread(long id) {
return findThread(id, DEFAULT_STACK_TRACE_MAX_DEPTH);
}
public static ThreadInfo findThread(long id, int stackTraceMaxDepth) {
if (stackTraceMaxDepth <= 0) {
return THREAD_MX_BEAN.getThreadInfo(id);
} else {
return THREAD_MX_BEAN.getThreadInfo(id, stackTraceMaxDepth);
}
}
public static List<ThreadInfo> findThread(String threadName) {
Asserts.notNull(threadName, "threadName may not be null.");
ThreadInfo[] threadInfos = dumpAllThread();
if (threadInfos == null) {
return Collections.emptyList();
}
ArrayList<ThreadInfo> threadInfoList = new ArrayList<ThreadInfo>(1);
for (ThreadInfo threadInfo : threadInfos) {
if (threadName.equals(threadInfo.getThreadName())) {
threadInfoList.add(threadInfo);
}
}
return threadInfoList;
}
public static boolean findThreadName(ThreadInfo[] threadInfos, String threadName) {
if (threadInfos == null) {
return false;
}
for (ThreadInfo threadInfo : threadInfos) {
if (threadInfo.getThreadName().equals(threadName)) {
return true;
}
}
return false;
}
public static boolean findThreadName(String threadName) {
final ThreadInfo[] threadInfos = dumpAllThread();
return findThreadName(threadInfos, threadName);
}
}