001/** 002 * 003 * Licensed to the Apache Software Foundation (ASF) under one 004 * or more contributor license agreements. See the NOTICE file 005 * distributed with this work for additional information 006 * regarding copyright ownership. The ASF licenses this file 007 * to you under the Apache License, Version 2.0 (the 008 * "License"); you may not use this file except in compliance 009 * with the License. You may obtain a copy of the License at 010 * 011 * http://www.apache.org/licenses/LICENSE-2.0 012 * 013 * Unless required by applicable law or agreed to in writing, software 014 * distributed under the License is distributed on an "AS IS" BASIS, 015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 016 * See the License for the specific language governing permissions and 017 * limitations under the License. 018 */ 019package org.apache.hadoop.hbase.monitoring; 020 021import java.lang.management.ManagementFactory; 022import java.lang.management.ThreadInfo; 023import java.lang.management.ThreadMXBean; 024 025import org.apache.yetus.audience.InterfaceAudience; 026 027@InterfaceAudience.Private 028public abstract class ThreadMonitoring { 029 030 private static final ThreadMXBean threadBean = 031 ManagementFactory.getThreadMXBean(); 032 private static final int STACK_DEPTH = 20; 033 034 public static ThreadInfo getThreadInfo(Thread t) { 035 long tid = t.getId(); 036 return threadBean.getThreadInfo(tid, STACK_DEPTH); 037 } 038 039 040 /** 041 * Format the given ThreadInfo object as a String. 042 * @param indent a prefix for each line, used for nested indentation 043 */ 044 public static String formatThreadInfo(ThreadInfo threadInfo, String indent) { 045 StringBuilder sb = new StringBuilder(); 046 appendThreadInfo(sb, threadInfo, indent); 047 return sb.toString(); 048 } 049 050 /** 051 * Print all of the thread's information and stack traces. 052 * 053 * @param sb 054 * @param info 055 * @param indent 056 */ 057 public static void appendThreadInfo(StringBuilder sb, 058 ThreadInfo info, 059 String indent) { 060 boolean contention = threadBean.isThreadContentionMonitoringEnabled(); 061 062 if (info == null) { 063 sb.append(indent).append("Inactive (perhaps exited while monitoring was done)\n"); 064 return; 065 } 066 String taskName = getTaskName(info.getThreadId(), info.getThreadName()); 067 sb.append(indent).append("Thread ").append(taskName).append(":\n"); 068 069 Thread.State state = info.getThreadState(); 070 sb.append(indent).append(" State: ").append(state).append("\n"); 071 sb.append(indent).append(" Blocked count: ").append(info.getBlockedCount()).append("\n"); 072 sb.append(indent).append(" Waited count: ").append(info.getWaitedCount()).append("\n"); 073 if (contention) { 074 sb.append(indent).append(" Blocked time: " + info.getBlockedTime()).append("\n"); 075 sb.append(indent).append(" Waited time: " + info.getWaitedTime()).append("\n"); 076 } 077 if (state == Thread.State.WAITING) { 078 sb.append(indent).append(" Waiting on ").append(info.getLockName()).append("\n"); 079 } else if (state == Thread.State.BLOCKED) { 080 sb.append(indent).append(" Blocked on ").append(info.getLockName()).append("\n"); 081 sb.append(indent).append(" Blocked by ").append( 082 getTaskName(info.getLockOwnerId(), info.getLockOwnerName())).append("\n"); 083 } 084 sb.append(indent).append(" Stack:").append("\n"); 085 for (StackTraceElement frame: info.getStackTrace()) { 086 sb.append(indent).append(" ").append(frame.toString()).append("\n"); 087 } 088 } 089 090 private static String getTaskName(long id, String name) { 091 if (name == null) { 092 return Long.toString(id); 093 } 094 return id + " (" + name + ")"; 095 } 096 097 098}