mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			896 lines
		
	
	
		
			34 KiB
		
	
	
	
		
			Java
		
	
	
	
			
		
		
	
	
			896 lines
		
	
	
		
			34 KiB
		
	
	
	
		
			Java
		
	
	
	
/* ThreadInfo.java - Information on a thread
 | 
						|
   Copyright (C) 2006 Free Software Foundation
 | 
						|
 | 
						|
This file is part of GNU Classpath.
 | 
						|
 | 
						|
GNU Classpath is free software; you can redistribute it and/or modify
 | 
						|
it under the terms of the GNU General Public License as published by
 | 
						|
the Free Software Foundation; either version 2, or (at your option)
 | 
						|
any later version.
 | 
						|
 | 
						|
GNU Classpath is distributed in the hope that it will be useful, but
 | 
						|
WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
						|
General Public License for more details.
 | 
						|
 | 
						|
You should have received a copy of the GNU General Public License
 | 
						|
along with GNU Classpath; see the file COPYING.  If not, write to the
 | 
						|
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 | 
						|
02110-1301 USA.
 | 
						|
 | 
						|
Linking this library statically or dynamically with other modules is
 | 
						|
making a combined work based on this library.  Thus, the terms and
 | 
						|
conditions of the GNU General Public License cover the whole
 | 
						|
combination.
 | 
						|
 | 
						|
As a special exception, the copyright holders of this library give you
 | 
						|
permission to link this library with independent modules to produce an
 | 
						|
executable, regardless of the license terms of these independent
 | 
						|
modules, and to copy and distribute the resulting executable under
 | 
						|
terms of your choice, provided that you also meet, for each linked
 | 
						|
independent module, the terms and conditions of the license of that
 | 
						|
module.  An independent module is a module which is not derived from
 | 
						|
or based on this library.  If you modify this library, you may extend
 | 
						|
this exception to your version of the library, but you are not
 | 
						|
obligated to do so.  If you do not wish to do so, delete this
 | 
						|
exception statement from your version. */
 | 
						|
 | 
						|
package java.lang.management;
 | 
						|
 | 
						|
import java.util.Arrays;
 | 
						|
 | 
						|
import javax.management.openmbean.ArrayType;
 | 
						|
import javax.management.openmbean.CompositeData;
 | 
						|
import javax.management.openmbean.CompositeType;
 | 
						|
import javax.management.openmbean.OpenDataException;
 | 
						|
import javax.management.openmbean.OpenType;
 | 
						|
import javax.management.openmbean.SimpleType;
 | 
						|
 | 
						|
/**
 | 
						|
 * <p>
 | 
						|
 * A class which maintains information about a particular
 | 
						|
 * thread.  This information includes:
 | 
						|
 * </p>
 | 
						|
 * <ul>
 | 
						|
 * <li><strong>General Thread Information:</strong>
 | 
						|
 * <ul>
 | 
						|
 * <li>The identifier of the thread.</li>
 | 
						|
 * <li>The name of the thread.</li>
 | 
						|
 * </ul>
 | 
						|
 * </li>
 | 
						|
 * <li><strong>Execution Information:</strong>
 | 
						|
 * <ul>
 | 
						|
 * <li>The current state of the thread (e.g. blocked, runnable)</li>
 | 
						|
 * <li>The object upon which the thread is blocked, either because
 | 
						|
 * the thread is waiting to obtain the monitor of that object to enter
 | 
						|
 * one of its synchronized monitor, or because
 | 
						|
 * {@link java.lang.Object#wait()} has been called while the thread
 | 
						|
 * was within a method of that object.</li>
 | 
						|
 * <li>The thread identifier of the current thread holding an object's
 | 
						|
 * monitor, upon which the thread described here is blocked.</li>
 | 
						|
 * <li>The stack trace of the thread (if requested on creation
 | 
						|
 * of this object</li>
 | 
						|
 * <li>The current locks held on object monitors by the thread.</li>
 | 
						|
 * <li>The current locks held on ownable synchronizers by the thread.</li>
 | 
						|
 * </ul>
 | 
						|
 * <li><strong>Synchronization Statistics</strong>
 | 
						|
 * <ul>
 | 
						|
 * <li>The number of times the thread has been blocked waiting for
 | 
						|
 * an object's monitor or in a {@link java.lang.Object#wait()} call.</li>
 | 
						|
 * <li>The accumulated time the thread has been blocked waiting for
 | 
						|
 * an object's monitor on in a {@link java.lang.Object#wait()} call.
 | 
						|
 * The availability of these statistics depends on the virtual machine's
 | 
						|
 * support for thread contention monitoring (see
 | 
						|
 * {@link ThreadMXBean#isThreadContentionMonitoringSupported()}.</li>
 | 
						|
 * </ul>
 | 
						|
 * </li>
 | 
						|
 * </ul>
 | 
						|
 *
 | 
						|
 * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
 | 
						|
 * @since 1.5
 | 
						|
 * @see ThreadMXBean#isThreadContentionMonitoringSupported()
 | 
						|
 */
 | 
						|
public class ThreadInfo
 | 
						|
{
 | 
						|
 | 
						|
  /**
 | 
						|
   * The id of the thread which this instance concerns.
 | 
						|
   */
 | 
						|
  private long threadId;
 | 
						|
 | 
						|
  /**
 | 
						|
   * The name of the thread which this instance concerns.
 | 
						|
   */
 | 
						|
  private String threadName;
 | 
						|
 | 
						|
  /**
 | 
						|
   * The state of the thread which this instance concerns.
 | 
						|
   */
 | 
						|
  private Thread.State threadState;
 | 
						|
 | 
						|
  /**
 | 
						|
   * The number of times the thread has been blocked.
 | 
						|
   */
 | 
						|
  private long blockedCount;
 | 
						|
 | 
						|
  /**
 | 
						|
   * The accumulated number of milliseconds the thread has
 | 
						|
   * been blocked (used only with thread contention monitoring
 | 
						|
   * support).
 | 
						|
   */
 | 
						|
  private long blockedTime;
 | 
						|
 | 
						|
  /**
 | 
						|
   * The name of the monitor lock on which this thread
 | 
						|
   * is blocked (if any).
 | 
						|
   */
 | 
						|
  private String lockName;
 | 
						|
 | 
						|
  /**
 | 
						|
   * The id of the thread which owns the monitor lock on
 | 
						|
   * which this thread is blocked, or <code>-1</code>
 | 
						|
   * if there is no owner.
 | 
						|
   */
 | 
						|
  private long lockOwnerId;
 | 
						|
 | 
						|
  /**
 | 
						|
   * The name of the thread which owns the monitor lock on
 | 
						|
   * which this thread is blocked, or <code>null</code>
 | 
						|
   * if there is no owner.
 | 
						|
   */
 | 
						|
  private String lockOwnerName;
 | 
						|
 | 
						|
  /**
 | 
						|
   * The number of times the thread has been in a waiting
 | 
						|
   * state.
 | 
						|
   */
 | 
						|
  private long waitedCount;
 | 
						|
 | 
						|
  /**
 | 
						|
   * The accumulated number of milliseconds the thread has
 | 
						|
   * been waiting (used only with thread contention monitoring
 | 
						|
   * support).
 | 
						|
   */
 | 
						|
  private long waitedTime;
 | 
						|
 | 
						|
  /**
 | 
						|
   * True if the thread is in a native method.
 | 
						|
   */
 | 
						|
  private boolean isInNative;
 | 
						|
 | 
						|
  /**
 | 
						|
   * True if the thread is suspended.
 | 
						|
   */
 | 
						|
  private boolean isSuspended;
 | 
						|
 | 
						|
  /**
 | 
						|
   * The stack trace of the thread.
 | 
						|
   */
 | 
						|
  private StackTraceElement[] trace;
 | 
						|
 | 
						|
  /**
 | 
						|
   * The array of information on monitors locked by the thread.
 | 
						|
   */
 | 
						|
  private MonitorInfo[] lockedMonitors;
 | 
						|
 | 
						|
  /**
 | 
						|
   * The array of information on ownable synchronizers locked
 | 
						|
   * by the thread.
 | 
						|
   */
 | 
						|
  private LockInfo[] lockedSynchronizers;
 | 
						|
 | 
						|
  /**
 | 
						|
   * Cache a local reference to the thread management bean.
 | 
						|
   */
 | 
						|
  private static ThreadMXBean bean = null;
 | 
						|
 | 
						|
  /**
 | 
						|
   * Cache the {@link javax.management.openmbean.CompositeType}
 | 
						|
   * for the {@link StackTraceElement}.
 | 
						|
   */
 | 
						|
  private static CompositeType seType;
 | 
						|
 | 
						|
  /**
 | 
						|
   * Constructs a new {@link ThreadInfo} corresponding
 | 
						|
   * to the thread details specified.
 | 
						|
   *
 | 
						|
   * @param threadId the id of the thread on which this
 | 
						|
   *                 new instance will be based.
 | 
						|
   * @param threadName the name of the thread on which
 | 
						|
   *                 this new instance will be based.
 | 
						|
   * @param threadState the state of the thread on which
 | 
						|
   *                 this new instance will be based.
 | 
						|
   * @param blockedCount the number of times the thread
 | 
						|
   *                     has been blocked.
 | 
						|
   * @param blockedTime the accumulated number of milliseconds
 | 
						|
   *                    the specified thread has been blocked
 | 
						|
   *                    (only used with contention monitoring enabled)
 | 
						|
   * @param lockName the name of the monitor lock the thread is waiting for
 | 
						|
   *                 (only used if blocked)
 | 
						|
   * @param lockOwnerId the id of the thread which owns the monitor
 | 
						|
   *                  lock, or <code>-1</code> if it doesn't have an owner
 | 
						|
   *                  (only used if blocked)
 | 
						|
   * @param lockOwnerName the name of the thread which owns the monitor
 | 
						|
   *                  lock, or <code>null</code> if it doesn't have an
 | 
						|
   *                  owner (only used if blocked)
 | 
						|
   * @param waitedCount the number of times the thread has been in a
 | 
						|
   *                    waiting state.
 | 
						|
   * @param waitedTime the accumulated number of milliseconds the
 | 
						|
   *                   specified thread has been waiting
 | 
						|
   *                   (only used with contention monitoring enabled)
 | 
						|
   * @param isInNative true if the thread is in a native method.
 | 
						|
   * @param isSuspended true if the thread is suspended.
 | 
						|
   * @param trace the stack trace of the thread to a pre-determined
 | 
						|
   *              depth (see VMThreadMXBeanImpl)
 | 
						|
   * @param lockedMonitors an array of {@link MonitorInfo} objects
 | 
						|
   *                       representing locks held on object monitors
 | 
						|
   *                       by the thread.
 | 
						|
   * @param lockedSynchronizers an array of {@link LockInfo} objects
 | 
						|
   *                            representing locks held on ownable
 | 
						|
   *                            synchronizers by the thread.
 | 
						|
   *
 | 
						|
   * @since 1.6
 | 
						|
   */
 | 
						|
  private ThreadInfo(long threadId, String threadName, Thread.State threadState,
 | 
						|
                     long blockedCount, long blockedTime, String lockName,
 | 
						|
                     long lockOwnerId, String lockOwnerName, long waitedCount,
 | 
						|
                     long waitedTime, boolean isInNative, boolean isSuspended,
 | 
						|
                     StackTraceElement[] trace, MonitorInfo[] lockedMonitors,
 | 
						|
                     LockInfo[] lockedSynchronizers)
 | 
						|
  {
 | 
						|
    this.threadId = threadId;
 | 
						|
    this.threadName = threadName;
 | 
						|
    this.threadState = threadState;
 | 
						|
    this.blockedCount = blockedCount;
 | 
						|
    this.blockedTime = blockedTime;
 | 
						|
    this.lockName = lockName;
 | 
						|
    this.lockOwnerId = lockOwnerId;
 | 
						|
    this.lockOwnerName = lockOwnerName;
 | 
						|
    this.waitedCount = waitedCount;
 | 
						|
    this.waitedTime = waitedTime;
 | 
						|
    this.isInNative = isInNative;
 | 
						|
    this.isSuspended = isSuspended;
 | 
						|
    this.trace = trace;
 | 
						|
    this.lockedMonitors = lockedMonitors;
 | 
						|
    this.lockedSynchronizers = lockedSynchronizers;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Checks for an attribute in a {@link CompositeData} structure
 | 
						|
   * with the correct type.
 | 
						|
   *
 | 
						|
   * @param ctype the composite data type to check.
 | 
						|
   * @param name the name of the attribute.
 | 
						|
   * @param type the type to check for.
 | 
						|
   * @throws IllegalArgumentException if the attribute is absent
 | 
						|
   *                                  or of the wrong type.
 | 
						|
   */
 | 
						|
  static void checkAttribute(CompositeType ctype, String name,
 | 
						|
                             OpenType type)
 | 
						|
    throws IllegalArgumentException
 | 
						|
  {
 | 
						|
    OpenType foundType = ctype.getType(name);
 | 
						|
    if (foundType == null)
 | 
						|
      throw new IllegalArgumentException("Could not find a field named " +
 | 
						|
                                         name);
 | 
						|
    if (!(foundType.equals(type)))
 | 
						|
      throw new IllegalArgumentException("Field " + name + " is not of " +
 | 
						|
                                         "type " + type.getClassName());
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Returns the {@link javax.management.openmbean.CompositeType} for
 | 
						|
   * a {@link StackTraceElement}.
 | 
						|
   *
 | 
						|
   * @return the type for the stack trace element.
 | 
						|
   */
 | 
						|
  static CompositeType getStackTraceType()
 | 
						|
  {
 | 
						|
    if (seType == null)
 | 
						|
      try
 | 
						|
        {
 | 
						|
          seType = new CompositeType(StackTraceElement.class.getName(),
 | 
						|
                                     "An element of a stack trace",
 | 
						|
                                     new String[] { "className", "methodName",
 | 
						|
                                                    "fileName", "lineNumber",
 | 
						|
                                                    "nativeMethod"
 | 
						|
                                     },
 | 
						|
                                     new String[] { "Name of the class",
 | 
						|
                                                    "Name of the method",
 | 
						|
                                                    "Name of the source code file",
 | 
						|
                                                    "Line number",
 | 
						|
                                                    "True if this is a native method"
 | 
						|
                                     },
 | 
						|
                                     new OpenType[] {
 | 
						|
                                       SimpleType.STRING, SimpleType.STRING,
 | 
						|
                                       SimpleType.STRING, SimpleType.INTEGER,
 | 
						|
                                       SimpleType.BOOLEAN
 | 
						|
                                     });
 | 
						|
        }
 | 
						|
      catch (OpenDataException e)
 | 
						|
        {
 | 
						|
          throw new IllegalStateException("Something went wrong in creating " +
 | 
						|
                                          "the composite data type for the " +
 | 
						|
                                          "stack trace element.", e);
 | 
						|
        }
 | 
						|
    return seType;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * <p>
 | 
						|
   * Returns a {@link ThreadInfo} instance using the values
 | 
						|
   * given in the supplied
 | 
						|
   * {@link javax.management.openmbean.CompositeData} object.
 | 
						|
   * The composite data instance should contain the following
 | 
						|
   * attributes with the specified types:
 | 
						|
   * </p>
 | 
						|
   * <table>
 | 
						|
   * <th><td>Name</td><td>Type</td></th>
 | 
						|
   * <tr><td>threadId</td><td>java.lang.Long</td></tr>
 | 
						|
   * <tr><td>threadName</td><td>java.lang.String</td></tr>
 | 
						|
   * <tr><td>threadState</td><td>java.lang.String</td></tr>
 | 
						|
   * <tr><td>suspended</td><td>java.lang.Boolean</td></tr>
 | 
						|
   * <tr><td>inNative</td><td>java.lang.Boolean</td></tr>
 | 
						|
   * <tr><td>blockedCount</td><td>java.lang.Long</td></tr>
 | 
						|
   * <tr><td>blockedTime</td><td>java.lang.Long</td></tr>
 | 
						|
   * <tr><td>waitedCount</td><td>java.lang.Long</td></tr>
 | 
						|
   * <tr><td>waitedTime</td><td>java.lang.Long</td></tr>
 | 
						|
   * <tr><td>lockName</td><td>java.lang.String</td></tr>
 | 
						|
   * <tr><td>lockOwnerId</td><td>java.lang.Long</td></tr>
 | 
						|
   * <tr><td>lockOwnerName</td><td>java.lang.String</td></tr>
 | 
						|
   * <tr><td>stackTrace</td><td>javax.management.openmbean.CompositeData[]
 | 
						|
   * </td></tr>
 | 
						|
   * </table>
 | 
						|
   * <p>
 | 
						|
   * The stack trace is further described as:
 | 
						|
   * </p>
 | 
						|
   * <table>
 | 
						|
   * <th><td>Name</td><td>Type</td></th>
 | 
						|
   * <tr><td>className</td><td>java.lang.String</td></tr>
 | 
						|
   * <tr><td>methodName</td><td>java.lang.String</td></tr>
 | 
						|
   * <tr><td>fileName</td><td>java.lang.String</td></tr>
 | 
						|
   * <tr><td>lineNumber</td><td>java.lang.Integer</td></tr>
 | 
						|
   * <tr><td>nativeMethod</td><td>java.lang.Boolean</td></tr>
 | 
						|
   * </table>
 | 
						|
   *
 | 
						|
   * @param data the composite data structure to take values from.
 | 
						|
   * @return a new instance containing the values from the
 | 
						|
   *         composite data structure, or <code>null</code>
 | 
						|
   *         if the data structure was also <code>null</code>.
 | 
						|
   * @throws IllegalArgumentException if the composite data structure
 | 
						|
   *                                  does not match the structure
 | 
						|
   *                                  outlined above.
 | 
						|
   */
 | 
						|
  public static ThreadInfo from(CompositeData data)
 | 
						|
  {
 | 
						|
    if (data == null)
 | 
						|
      return null;
 | 
						|
    CompositeType type = data.getCompositeType();
 | 
						|
    checkAttribute(type, "ThreadId", SimpleType.LONG);
 | 
						|
    checkAttribute(type, "ThreadName", SimpleType.STRING);
 | 
						|
    checkAttribute(type, "ThreadState", SimpleType.STRING);
 | 
						|
    checkAttribute(type, "Suspended", SimpleType.BOOLEAN);
 | 
						|
    checkAttribute(type, "InNative", SimpleType.BOOLEAN);
 | 
						|
    checkAttribute(type, "BlockedCount", SimpleType.LONG);
 | 
						|
    checkAttribute(type, "BlockedTime", SimpleType.LONG);
 | 
						|
    checkAttribute(type, "WaitedCount", SimpleType.LONG);
 | 
						|
    checkAttribute(type, "WaitedTime", SimpleType.LONG);
 | 
						|
    checkAttribute(type, "LockName", SimpleType.STRING);
 | 
						|
    checkAttribute(type, "LockOwnerId", SimpleType.LONG);
 | 
						|
    checkAttribute(type, "LockOwnerName", SimpleType.STRING);
 | 
						|
    try
 | 
						|
      {
 | 
						|
        checkAttribute(type, "StackTrace",
 | 
						|
                       new ArrayType(1, getStackTraceType()));
 | 
						|
      }
 | 
						|
    catch (OpenDataException e)
 | 
						|
      {
 | 
						|
        throw new IllegalStateException("Something went wrong in creating " +
 | 
						|
                                        "the array for the stack trace element.",
 | 
						|
                                        e);
 | 
						|
      }
 | 
						|
    OpenType foundType = type.getType("LockedMonitors");
 | 
						|
    if (foundType != null)
 | 
						|
      try
 | 
						|
        {
 | 
						|
          CompositeType mType = new CompositeType(MonitorInfo.class.getName(),
 | 
						|
                                                  "Information on a object monitor lock",
 | 
						|
                                                  new String[] { "ClassName",
 | 
						|
                                                                 "IdentityHashCode",
 | 
						|
                                                                 "LockedStackDepth",
 | 
						|
                                                                 "LockedStackFrame"
 | 
						|
                                                  },
 | 
						|
                                                  new String[] { "Name of the class",
 | 
						|
                                                                 "Identity hash code " +
 | 
						|
                                                                 "of the class",
 | 
						|
                                                                 "Stack depth at time " +
 | 
						|
                                                                 "of lock",
 | 
						|
                                                                 "Stack frame at time " +
 | 
						|
                                                                 "of lock",
 | 
						|
                                                  },
 | 
						|
                                                  new OpenType[] {
 | 
						|
                                                    SimpleType.STRING, SimpleType.INTEGER,
 | 
						|
                                                    SimpleType.INTEGER, getStackTraceType()
 | 
						|
                                                  });
 | 
						|
          if (!(foundType.equals(new ArrayType(1, mType))))
 | 
						|
            throw new IllegalArgumentException("Field LockedMonitors is not of " +
 | 
						|
                                               "type " + mType.getClassName());
 | 
						|
        }
 | 
						|
    catch (OpenDataException e)
 | 
						|
      {
 | 
						|
        throw new IllegalStateException("Something went wrong in creating " +
 | 
						|
                                        "the composite data type for the " +
 | 
						|
                                        "object monitor information array.", e);
 | 
						|
      }
 | 
						|
    foundType = type.getType("LockedSynchronizers");
 | 
						|
    if (foundType != null)
 | 
						|
      try
 | 
						|
        {
 | 
						|
          CompositeType lType = new CompositeType(LockInfo.class.getName(),
 | 
						|
                                                  "Information on a lock",
 | 
						|
                                                  new String[] { "ClassName",
 | 
						|
                                                                 "IdentityHashCode"
 | 
						|
                                                  },
 | 
						|
                                                  new String[] { "Name of the class",
 | 
						|
                                                                 "Identity hash code " +
 | 
						|
                                                                 "of the class"
 | 
						|
                                                  },
 | 
						|
                                                  new OpenType[] {
 | 
						|
                                                    SimpleType.STRING, SimpleType.INTEGER
 | 
						|
                                                  });
 | 
						|
          if (!(foundType.equals(new ArrayType(1, lType))))
 | 
						|
            throw new IllegalArgumentException("Field LockedSynchronizers is not of " +
 | 
						|
                                               "type " + lType.getClassName());
 | 
						|
        }
 | 
						|
    catch (OpenDataException e)
 | 
						|
      {
 | 
						|
        throw new IllegalStateException("Something went wrong in creating " +
 | 
						|
                                        "the composite data type for the " +
 | 
						|
                                        "ownable synchronizerinformation array.", e);
 | 
						|
      }
 | 
						|
    CompositeData[] dTraces = (CompositeData[]) data.get("StackTrace");
 | 
						|
    StackTraceElement[] traces = new StackTraceElement[dTraces.length];
 | 
						|
    for (int a = 0; a < dTraces.length; ++a)
 | 
						|
        /* FIXME: We can't use the boolean as there is no available
 | 
						|
           constructor. */
 | 
						|
      traces[a] =
 | 
						|
        new StackTraceElement((String) dTraces[a].get("ClassName"),
 | 
						|
                              (String) dTraces[a].get("MethodName"),
 | 
						|
                              (String) dTraces[a].get("FileName"),
 | 
						|
                              ((Integer)
 | 
						|
                               dTraces[a].get("LineNumber")).intValue());
 | 
						|
    MonitorInfo[] mInfo;
 | 
						|
    if (data.containsKey("LockedMonitors"))
 | 
						|
      {
 | 
						|
        CompositeData[] dmInfos = (CompositeData[]) data.get("LockedMonitors");
 | 
						|
        mInfo = new MonitorInfo[dmInfos.length];
 | 
						|
        for (int a = 0; a < dmInfos.length; ++a)
 | 
						|
          mInfo[a] = MonitorInfo.from(dmInfos[a]);
 | 
						|
      }
 | 
						|
    else
 | 
						|
      mInfo = new MonitorInfo[]{};
 | 
						|
    LockInfo[] lInfo;
 | 
						|
    if (data.containsKey("LockedSynchronizers"))
 | 
						|
      {
 | 
						|
        CompositeData[] dlInfos = (CompositeData[]) data.get("LockedSynchronizers");
 | 
						|
        lInfo = new LockInfo[dlInfos.length];
 | 
						|
        for (int a = 0; a < dlInfos.length; ++a)
 | 
						|
          lInfo[a] = new LockInfo((String) dlInfos[a].get("ClassName"),
 | 
						|
                                  (Integer) dlInfos[a].get("IdentityHashCode"));
 | 
						|
      }
 | 
						|
    else
 | 
						|
      lInfo = new LockInfo[]{};
 | 
						|
    return new ThreadInfo(((Long) data.get("ThreadId")).longValue(),
 | 
						|
                          (String) data.get("ThreadName"),
 | 
						|
                          Thread.State.valueOf((String) data.get("ThreadState")),
 | 
						|
                          ((Long) data.get("BlockedCount")).longValue(),
 | 
						|
                          ((Long) data.get("BlockedTime")).longValue(),
 | 
						|
                          (String) data.get("LockName"),
 | 
						|
                          ((Long) data.get("LockOwnerId")).longValue(),
 | 
						|
                          (String) data.get("LockOwnerName"),
 | 
						|
                          ((Long) data.get("WaitedCount")).longValue(),
 | 
						|
                          ((Long) data.get("WaitedTime")).longValue(),
 | 
						|
                          ((Boolean) data.get("InNative")).booleanValue(),
 | 
						|
                          ((Boolean) data.get("Suspended")).booleanValue(),
 | 
						|
                          traces, mInfo, lInfo);
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Returns the number of times this thread has been
 | 
						|
   * in the {@link java.lang.Thread.State#BLOCKED} state.
 | 
						|
   * A thread enters this state when it is waiting to
 | 
						|
   * obtain an object's monitor.  This may occur either
 | 
						|
   * on entering a synchronized method for the first time,
 | 
						|
   * or on re-entering it following a call to
 | 
						|
   * {@link java.lang.Object#wait()}.
 | 
						|
   *
 | 
						|
   * @return the number of times this thread has been blocked.
 | 
						|
   */
 | 
						|
  public long getBlockedCount()
 | 
						|
  {
 | 
						|
    return blockedCount;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * <p>
 | 
						|
   * Returns the accumulated number of milliseconds this
 | 
						|
   * thread has been in the
 | 
						|
   * {@link java.lang.Thread.State#BLOCKED} state
 | 
						|
   * since thread contention monitoring was last enabled.
 | 
						|
   * A thread enters this state when it is waiting to
 | 
						|
   * obtain an object's monitor.  This may occur either
 | 
						|
   * on entering a synchronized method for the first time,
 | 
						|
   * or on re-entering it following a call to
 | 
						|
   * {@link java.lang.Object#wait()}.
 | 
						|
   * </p>
 | 
						|
   * <p>
 | 
						|
   * Use of this method requires virtual machine support
 | 
						|
   * for thread contention monitoring and for this support
 | 
						|
   * to be enabled.
 | 
						|
   * </p>
 | 
						|
   *
 | 
						|
   * @return the accumulated time (in milliseconds) that this
 | 
						|
   *         thread has spent in the blocked state, since
 | 
						|
   *         thread contention monitoring was enabled, or -1
 | 
						|
   *         if thread contention monitoring is disabled.
 | 
						|
   * @throws UnsupportedOperationException if the virtual
 | 
						|
   *                                       machine does not
 | 
						|
   *                                       support contention
 | 
						|
   *                                       monitoring.
 | 
						|
   * @see ThreadMXBean#isThreadContentionMonitoringEnabled()
 | 
						|
   * @see ThreadMXBean#isThreadContentionMonitoringSupported()
 | 
						|
   */
 | 
						|
  public long getBlockedTime()
 | 
						|
  {
 | 
						|
    if (bean == null)
 | 
						|
      bean = ManagementFactory.getThreadMXBean();
 | 
						|
    // Will throw UnsupportedOperationException for us
 | 
						|
    if (bean.isThreadContentionMonitoringEnabled())
 | 
						|
      return blockedTime;
 | 
						|
    else
 | 
						|
      return -1;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Returns an array of {@link MonitorInfo} objects representing
 | 
						|
   * information on the locks on object monitors held by the thread.
 | 
						|
   * If no locks are held, or such information was not requested
 | 
						|
   * on creating this {@link ThreadInfo} object, a zero-length
 | 
						|
   * array will be returned.
 | 
						|
   *
 | 
						|
   * @return information on object monitors locked by this thread.
 | 
						|
   */
 | 
						|
  public MonitorInfo[] getLockedMonitors()
 | 
						|
  {
 | 
						|
    return lockedMonitors;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Returns an array of {@link LockInfo} objects representing
 | 
						|
   * information on the locks on ownable synchronizers held by the thread.
 | 
						|
   * If no locks are held, or such information was not requested
 | 
						|
   * on creating this {@link ThreadInfo} object, a zero-length
 | 
						|
   * array will be returned.
 | 
						|
   *
 | 
						|
   * @return information on ownable synchronizers locked by this thread.
 | 
						|
   */
 | 
						|
  public LockInfo[] getLockedSynchronizers()
 | 
						|
  {
 | 
						|
    return lockedSynchronizers;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * <p>
 | 
						|
   * Returns a {@link LockInfo} object representing the
 | 
						|
   * lock on which this thread is blocked.  If the thread
 | 
						|
   * is not blocked, this method returns <code>null</code>.
 | 
						|
   * </p>
 | 
						|
   * <p>
 | 
						|
   * The thread may be blocked due to one of three reasons:
 | 
						|
   * </p>
 | 
						|
   * <ol>
 | 
						|
   * <li>The thread is in the <code>BLOCKED</code> state
 | 
						|
   * waiting to acquire an object monitor in order to enter
 | 
						|
   * a synchronized method or block.</li>
 | 
						|
   * <li>The thread is in the <code>WAITING</code> or
 | 
						|
   * <code>TIMED_WAITING</code> state due to a call to
 | 
						|
   * {@link java.lang.Object#wait()}.</li>
 | 
						|
   * <li>The thread is in the <code>WAITING</code> or
 | 
						|
   * <code>TIMED_WAITING</code> state due to a call
 | 
						|
   * to {@link java.util.concurrent.locks.LockSupport#park()}.
 | 
						|
   * The lock is the return value of
 | 
						|
   * {@link java.util.concurrent.locks.LockSupport#getBlocker()}.</li>
 | 
						|
   * </ol>
 | 
						|
   *
 | 
						|
   * @return a {@link LockInfo} object representing the lock on
 | 
						|
   *         which the thread is blocked, or <code>null</code> if
 | 
						|
   *         the thread isn't blocked.
 | 
						|
   * @since 1.6
 | 
						|
   * @see #getLockName()
 | 
						|
   */
 | 
						|
  public LockInfo getLockInfo()
 | 
						|
  {
 | 
						|
    String lockName = getLockName();
 | 
						|
    int at = lockName.indexOf('@');
 | 
						|
    return new LockInfo(lockName.substring(0, at),
 | 
						|
                        Integer.decode(lockName.substring(at + 1)));
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * <p>
 | 
						|
   * Returns a {@link java.lang.String} representation of
 | 
						|
   * the lock on which this thread is blocked.  If
 | 
						|
   * the thread is not blocked, this method returns
 | 
						|
   * <code>null</code>.
 | 
						|
   * </p>
 | 
						|
   * <p>
 | 
						|
   * The returned {@link java.lang.String} is constructed
 | 
						|
   * using the class name and identity hashcode (usually
 | 
						|
   * the memory address of the object) of the lock.  The
 | 
						|
   * two are separated by the '@' character, and the identity
 | 
						|
   * hashcode is represented in hexadecimal.  Thus, for a
 | 
						|
   * lock, <code>l</code>, the returned value is
 | 
						|
   * the result of concatenating
 | 
						|
   * <code>l.getClass().getName()</code>, <code>"@"</code>
 | 
						|
   * and
 | 
						|
   * <code>Integer.toHexString(System.identityHashCode(l))</code>.
 | 
						|
   * The value is only unique to the extent that the identity
 | 
						|
   * hash code is also unique.  The value is the same as would
 | 
						|
   * be returned by <code>getLockInfo().toString()</code>
 | 
						|
   * </p>
 | 
						|
   *
 | 
						|
   * @return a string representing the lock on which this
 | 
						|
   *         thread is blocked, or <code>null</code> if
 | 
						|
   *         the thread is not blocked.
 | 
						|
   */
 | 
						|
  public String getLockName()
 | 
						|
  {
 | 
						|
    if (!isThreadBlocked())
 | 
						|
      return null;
 | 
						|
    return lockName;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Returns the identifier of the thread which owns the
 | 
						|
   * monitor lock this thread is waiting for.  -1 is returned
 | 
						|
   * if either this thread is not blocked, or the lock is
 | 
						|
   * not held by any other thread.
 | 
						|
   *
 | 
						|
   * @return the thread identifier of thread holding the lock
 | 
						|
   *         this thread is waiting for, or -1 if the thread
 | 
						|
   *         is not blocked or the lock is not held by another
 | 
						|
   *         thread.
 | 
						|
   */
 | 
						|
  public long getLockOwnerId()
 | 
						|
  {
 | 
						|
    if (!isThreadBlocked())
 | 
						|
      return -1;
 | 
						|
    return lockOwnerId;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Returns the name of the thread which owns the
 | 
						|
   * monitor lock this thread is waiting for.  <code>null</code>
 | 
						|
   * is returned if either this thread is not blocked,
 | 
						|
   * or the lock is not held by any other thread.
 | 
						|
   *
 | 
						|
   * @return the thread identifier of thread holding the lock
 | 
						|
   *         this thread is waiting for, or <code>null</code>
 | 
						|
   *         if the thread is not blocked or the lock is not
 | 
						|
   *         held by another thread.
 | 
						|
   */
 | 
						|
  public String getLockOwnerName()
 | 
						|
  {
 | 
						|
    if (!isThreadBlocked())
 | 
						|
      return null;
 | 
						|
    return lockOwnerName;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * <p>
 | 
						|
   * Returns the stack trace of this thread to the depth
 | 
						|
   * specified on creation of this {@link ThreadInfo}
 | 
						|
   * object.  If the depth is zero, an empty array will
 | 
						|
   * be returned.  For non-zero arrays, the elements
 | 
						|
   * start with the most recent trace at position zero.
 | 
						|
   * The bottom of the stack represents the oldest method
 | 
						|
   * invocation which meets the depth requirements.
 | 
						|
   * </p>
 | 
						|
   * <p>
 | 
						|
   * Some virtual machines may not be able to return
 | 
						|
   * stack trace information for a thread.  In these
 | 
						|
   * cases, an empty array will also be returned.
 | 
						|
   * </p>
 | 
						|
   *
 | 
						|
   * @return an array of {@link java.lang.StackTraceElement}s
 | 
						|
   *         representing the trace of this thread.
 | 
						|
   */
 | 
						|
  public StackTraceElement[] getStackTrace()
 | 
						|
  {
 | 
						|
    return trace;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Returns the identifier of the thread associated with
 | 
						|
   * this instance of {@link ThreadInfo}.
 | 
						|
   *
 | 
						|
   * @return the thread's identifier.
 | 
						|
   */
 | 
						|
  public long getThreadId()
 | 
						|
  {
 | 
						|
    return threadId;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Returns the name of the thread associated with
 | 
						|
   * this instance of {@link ThreadInfo}.
 | 
						|
   *
 | 
						|
   * @return the thread's name.
 | 
						|
   */
 | 
						|
  public String getThreadName()
 | 
						|
  {
 | 
						|
    return threadName;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Returns the state of the thread associated with
 | 
						|
   * this instance of {@link ThreadInfo}.
 | 
						|
   *
 | 
						|
   * @return the thread's state.
 | 
						|
   */
 | 
						|
  public Thread.State getThreadState()
 | 
						|
  {
 | 
						|
    return threadState;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Returns the number of times this thread has been
 | 
						|
   * in the {@link java.lang.Thread.State#WAITING}
 | 
						|
   * or {@link java.lang.Thread.State#TIMED_WAITING} state.
 | 
						|
   * A thread enters one of these states when it is waiting
 | 
						|
   * due to a call to {@link java.lang.Object.wait()},
 | 
						|
   * {@link java.lang.Object.join()} or
 | 
						|
   * {@link java.lang.concurrent.locks.LockSupport.park()},
 | 
						|
   * either with an infinite or timed delay, respectively.
 | 
						|
   *
 | 
						|
   * @return the number of times this thread has been waiting.
 | 
						|
   */
 | 
						|
  public long getWaitedCount()
 | 
						|
  {
 | 
						|
    return waitedCount;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * <p>
 | 
						|
   * Returns the accumulated number of milliseconds this
 | 
						|
   * thread has been in the
 | 
						|
   * {@link java.lang.Thread.State#WAITING} or
 | 
						|
   * {@link java.lang.Thread.State#TIMED_WAITING} state,
 | 
						|
   * since thread contention monitoring was last enabled.
 | 
						|
   * A thread enters one of these states when it is waiting
 | 
						|
   * due to a call to {@link java.lang.Object.wait()},
 | 
						|
   * {@link java.lang.Object.join()} or
 | 
						|
   * {@link java.lang.concurrent.locks.LockSupport.park()},
 | 
						|
   * either with an infinite or timed delay, respectively.
 | 
						|
   * </p>
 | 
						|
   * <p>
 | 
						|
   * Use of this method requires virtual machine support
 | 
						|
   * for thread contention monitoring and for this support
 | 
						|
   * to be enabled.
 | 
						|
   * </p>
 | 
						|
   *
 | 
						|
   * @return the accumulated time (in milliseconds) that this
 | 
						|
   *         thread has spent in one of the waiting states, since
 | 
						|
   *         thread contention monitoring was enabled, or -1
 | 
						|
   *         if thread contention monitoring is disabled.
 | 
						|
   * @throws UnsupportedOperationException if the virtual
 | 
						|
   *                                       machine does not
 | 
						|
   *                                       support contention
 | 
						|
   *                                       monitoring.
 | 
						|
   * @see ThreadMXBean#isThreadContentionMonitoringEnabled()
 | 
						|
   * @see ThreadMXBean#isThreadContentionMonitoringSupported()
 | 
						|
   */
 | 
						|
  public long getWaitedTime()
 | 
						|
  {
 | 
						|
    if (bean == null)
 | 
						|
      bean = ManagementFactory.getThreadMXBean();
 | 
						|
    // Will throw UnsupportedOperationException for us
 | 
						|
    if (bean.isThreadContentionMonitoringEnabled())
 | 
						|
      return waitedTime;
 | 
						|
    else
 | 
						|
      return -1;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Returns true if the thread is in a native method.  This
 | 
						|
   * excludes native code which forms part of the virtual
 | 
						|
   * machine itself, or which results from Just-In-Time
 | 
						|
   * compilation.
 | 
						|
   *
 | 
						|
   * @return true if the thread is in a native method, false
 | 
						|
   *         otherwise.
 | 
						|
   */
 | 
						|
  public boolean isInNative()
 | 
						|
  {
 | 
						|
    return isInNative;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Returns true if the thread has been suspended using
 | 
						|
   * {@link java.lang.Thread#suspend()}.
 | 
						|
   *
 | 
						|
   * @return true if the thread is suspended, false otherwise.
 | 
						|
   */
 | 
						|
  public boolean isSuspended()
 | 
						|
  {
 | 
						|
    return isSuspended;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Returns a {@link java.lang.String} representation of
 | 
						|
   * this {@link ThreadInfo} object.  This takes the form
 | 
						|
   * <code>java.lang.management.ThreadInfo[id=tid, name=n,
 | 
						|
   * state=s, blockedCount=bc, waitedCount=wc, isInNative=iin,
 | 
						|
   * isSuspended=is]</code>, where <code>tid</code> is
 | 
						|
   * the thread identifier, <code>n</code> is the
 | 
						|
   * thread name, <code>s</code> is the thread state,
 | 
						|
   * <code>bc</code> is the blocked state count,
 | 
						|
   * <code>wc</code> is the waiting state count and
 | 
						|
   * <code>iin</code> and <code>is</code> are boolean
 | 
						|
   * flags to indicate the thread is in native code or
 | 
						|
   * suspended respectively.  If the thread is blocked,
 | 
						|
   * <code>lock=l, lockOwner=lo</code> is also included,
 | 
						|
   * where <code>l</code> is the lock waited for, and
 | 
						|
   * <code>lo</code> is the thread which owns the lock
 | 
						|
   * (or null if there is no owner).
 | 
						|
   *
 | 
						|
   * @return the string specified above.
 | 
						|
   */
 | 
						|
  public String toString()
 | 
						|
  {
 | 
						|
    return getClass().getName() +
 | 
						|
      "[id=" + threadId +
 | 
						|
      ", name=" + threadName +
 | 
						|
      ", state=" + threadState +
 | 
						|
      ", blockedCount=" + blockedCount +
 | 
						|
      ", waitedCount=" + waitedCount +
 | 
						|
      ", isInNative=" + isInNative +
 | 
						|
      ", isSuspended=" + isSuspended +
 | 
						|
      (isThreadBlocked() ?
 | 
						|
       ", lockOwnerId=" + lockOwnerId +
 | 
						|
       ", lockOwnerName=" + lockOwnerName : "") +
 | 
						|
      ", lockedMonitors=" + Arrays.toString(lockedMonitors) +
 | 
						|
      ", lockedSynchronizers=" + Arrays.toString(lockedSynchronizers) +
 | 
						|
      "]";
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * <p>
 | 
						|
   * Returns true if the thread is in a blocked state.
 | 
						|
   * The thread is regarded as blocked if:
 | 
						|
   * </p>
 | 
						|
   * <ol>
 | 
						|
   * <li>The thread is in the <code>BLOCKED</code> state
 | 
						|
   * waiting to acquire an object monitor in order to enter
 | 
						|
   * a synchronized method or block.</li>
 | 
						|
   * <li>The thread is in the <code>WAITING</code> or
 | 
						|
   * <code>TIMED_WAITING</code> state due to a call to
 | 
						|
   * {@link java.lang.Object#wait()}.</li>
 | 
						|
   * <li>The thread is in the <code>WAITING</code> or
 | 
						|
   * <code>TIMED_WAITING</code> state due to a call
 | 
						|
   * to {@link java.util.concurrent.locks.LockSupport#park()}.
 | 
						|
   * The lock is the return value of
 | 
						|
   * {@link java.util.concurrent.locks.LockSupport#getBlocker()}.</li>
 | 
						|
   * </ol>
 | 
						|
   *
 | 
						|
   * @return true if the thread is blocked.
 | 
						|
   */
 | 
						|
  private boolean isThreadBlocked()
 | 
						|
  {
 | 
						|
    return (threadState == Thread.State.BLOCKED ||
 | 
						|
            threadState == Thread.State.WAITING ||
 | 
						|
            threadState == Thread.State.TIMED_WAITING);
 | 
						|
  }
 | 
						|
 | 
						|
}
 |