blob: 6e0d873377ed1912a2c613a71233cf2012891569 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.logging.log4j.message;
import java.lang.management.LockInfo;
import java.lang.management.MonitorInfo;
import java.lang.management.ThreadInfo;
/**
* Provides information on locks and monitors in the thread dump. This class requires Java 1.6 to compile and
* run.
*/
class ExtendedThreadInformation implements ThreadInformation {
private final ThreadInfo info;
public ExtendedThreadInformation(ThreadInfo thread) {
this.info = thread;
}
public void printThreadInfo(StringBuilder sb) {
sb.append("\"").append(info.getThreadName()).append("\"");
sb.append(" Id=").append(info.getThreadId()).append(" ");
formatState(sb, info);
if (info.isSuspended()) {
sb.append(" (suspended)");
}
if (info.isInNative()) {
sb.append(" (in native)");
}
sb.append('\n');
}
public void printStack(StringBuilder sb, StackTraceElement[] stack) {
int i = 0;
for (StackTraceElement element : stack) {
sb.append("\tat ").append(element.toString());
sb.append('\n');
if (i == 0 && info.getLockInfo() != null) {
Thread.State ts = info.getThreadState();
switch (ts) {
case BLOCKED:
sb.append("\t- blocked on ");
formatLock(sb, info.getLockInfo());
sb.append('\n');
break;
case WAITING:
sb.append("\t- waiting on ");
formatLock(sb, info.getLockInfo());
sb.append('\n');
break;
case TIMED_WAITING:
sb.append("\t- waiting on ");
formatLock(sb, info.getLockInfo());
sb.append('\n');
break;
default:
}
}
for (MonitorInfo mi : info.getLockedMonitors()) {
if (mi.getLockedStackDepth() == i) {
sb.append("\t- locked ");
formatLock(sb, mi);
sb.append('\n');
}
}
++i;
}
LockInfo[] locks = info.getLockedSynchronizers();
if (locks.length > 0) {
sb.append("\n\tNumber of locked synchronizers = ").append(locks.length).append('\n');
for (LockInfo li : locks) {
sb.append("\t- ");
formatLock(sb, li);
sb.append('\n');
}
}
}
private void formatLock(StringBuilder sb, LockInfo lock) {
sb.append("<").append(lock.getIdentityHashCode()).append("> (a ");
sb.append(lock.getClassName()).append(")");
}
private void formatState(StringBuilder sb, ThreadInfo info) {
Thread.State state = info.getThreadState();
sb.append(state);
switch (state) {
case BLOCKED: {
sb.append(" (on object monitor owned by \"");
sb.append(info.getLockOwnerName()).append("\" Id=").append(info.getLockOwnerId()).append(")");
break;
}
case WAITING: {
StackTraceElement element = info.getStackTrace()[0];
String className = element.getClassName();
String method = element.getMethodName();
if (className.equals("java.lang.Object") && method.equals("wait")) {
sb.append(" (on object monitor");
if (info.getLockOwnerName() != null) {
sb.append(" owned by \"");
sb.append(info.getLockOwnerName()).append("\" Id=").append(info.getLockOwnerId());
}
sb.append(")");
} else if (className.equals("java.lang.Thread") && method.equals("join")) {
sb.append(" (on completion of thread ").append(info.getLockOwnerId()).append(")");
} else {
sb.append(" (parking for lock");
if (info.getLockOwnerName() != null) {
sb.append(" owned by \"");
sb.append(info.getLockOwnerName()).append("\" Id=").append(info.getLockOwnerId());
}
sb.append(")");
}
break;
}
case TIMED_WAITING: {
StackTraceElement element = info.getStackTrace()[0];
String className = element.getClassName();
String method = element.getMethodName();
if (className.equals("java.lang.Object") && method.equals("wait")) {
sb.append(" (on object monitor");
if (info.getLockOwnerName() != null) {
sb.append(" owned by \"");
sb.append(info.getLockOwnerName()).append("\" Id=").append(info.getLockOwnerId());
}
sb.append(")");
} else if (className.equals("java.lang.Thread") && method.equals("sleep")) {
sb.append(" (sleeping)");
} else if (className.equals("java.lang.Thread") && method.equals("join")) {
sb.append(" (on completion of thread ").append(info.getLockOwnerId()).append(")");
} else {
sb.append(" (parking for lock");
if (info.getLockOwnerName() != null) {
sb.append(" owned by \"");
sb.append(info.getLockOwnerName()).append("\" Id=").append(info.getLockOwnerId());
}
sb.append(")");
}
break;
}
default:
break;
}
}
}