From e1bea0c0687c5f4551b3a6058ec37ce3705fa6cc Mon Sep 17 00:00:00 2001
From: Matthias Klose
* Provides access to the system's management beans via a series
@@ -549,4 +565,253 @@ public class ManagementFactory
return platformServer;
}
+ /**
+ *
+ * Returns a proxy for the specified platform bean. A proxy object is created
+ * using
+ * Note: use of the proxy may result in
+ * {@link java.io.IOException}s from the underlying {@link MBeanServerConnection}
+ * and a {@link java.io.InvalidObjectException} if enum constants
+ * used on the client and the server don't match.
+ *
+ * Returns a {@link MonitorInfo} 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:
+ *
+ * The stack trace is further described as:
+ *
* Returns a {@link ThreadInfo} instance using the values
* given in the supplied
@@ -336,70 +494,133 @@ public class ThreadInfo
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);
+ 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
{
- CompositeType 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
- });
- checkAttribute(type, "stackTrace", new ArrayType(1, seType));
+ 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 " +
- "stack trace element.", e);
+ "ownable synchronizerinformation array.", e);
}
- CompositeData[] dTraces = (CompositeData[]) data.get("stackTrace");
+ 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"),
+ new StackTraceElement((String) dTraces[a].get("ClassName"),
+ (String) dTraces[a].get("MethodName"),
+ (String) dTraces[a].get("FileName"),
((Integer)
- dTraces[a].get("lineNumber")).intValue());
- 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);
+ 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);
}
/**
@@ -459,9 +680,74 @@ public class ThreadInfo
}
/**
+ * 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;
+ }
+
+ /**
+ *
+ * Returns a {@link LockInfo} object representing the
+ * lock on which this thread is blocked. If the thread
+ * is not blocked, this method returns
+ * The thread may be blocked due to one of three reasons:
+ *
* Returns a {@link java.lang.String} representation of
- * the monitor lock on which this thread is blocked. If
+ * the lock on which this thread is blocked. If
* the thread is not blocked, this method returns
* '@'
and the identity hash code
+ * in unsigned hexadecimal form.
+ *
+ * @return a textual representation of the lock.
+ */
+ public String toString()
+ {
+ return className + '@' + Integer.toHexString(identityHashCode);
+ }
+
+}
diff --git a/libjava/classpath/java/lang/management/ManagementFactory.java b/libjava/classpath/java/lang/management/ManagementFactory.java
index a51ca0f..977b399 100644
--- a/libjava/classpath/java/lang/management/ManagementFactory.java
+++ b/libjava/classpath/java/lang/management/ManagementFactory.java
@@ -49,20 +49,36 @@ import gnu.java.lang.management.MemoryPoolMXBeanImpl;
import gnu.java.lang.management.RuntimeMXBeanImpl;
import gnu.java.lang.management.ThreadMXBeanImpl;
+import java.io.IOException;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
+import java.util.Map;
import java.util.logging.LogManager;
+import javax.management.Attribute;
import javax.management.InstanceAlreadyExistsException;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
+import javax.management.MBeanServerConnection;
import javax.management.MBeanServerFactory;
import javax.management.MalformedObjectNameException;
import javax.management.NotCompliantMBeanException;
+import javax.management.NotificationEmitter;
+import javax.management.NotificationFilter;
+import javax.management.NotificationListener;
import javax.management.ObjectName;
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.TabularData;
+
/**
* Proxy.newProxyInstance(mxbeanInterface.getClassLoader(),
+ * new Class[] { mxbeanInterface }, handler)
. The
+ * {@link javax.management.NotificationEmitter} class is also added to the
+ * array if the bean provides notifications. handler
refers
+ * to the invocation handler which forwards calls to the connection, and
+ * also provides translation between the Java data types used in the
+ * bean interfaces and the open data types, as specified in the description
+ * of this class. It is this translation that makes the
+ * usual {@link javax.management.MBeanServerInvocationHandler} inappropriate
+ * for providing such a proxy.
+ * mxbeanName
is not a valid
+ * {@link javax.management.ObjectName},
+ * the interface and name do not match the
+ * same bean, the name does not refer to a
+ * platform bean or the bean is not registered
+ * with the server accessed by connection
.
+ * @throws IOException if the connection throws one.
+ */
+ public static null
but the depth is
+ * ≥ 0, or the frame is not
+ * null
but the depth is
+ * < 0.
+ */
+ public MonitorInfo(String className, int identityHashCode, int stackDepth,
+ StackTraceElement stackFrame)
+ {
+ super(className, identityHashCode);
+ if (stackFrame == null && stackDepth >= 0)
+ throw new IllegalArgumentException("The stack frame is null, but the " +
+ "stack depth is greater than or equal " +
+ "to zero.");
+ if (stackFrame != null && stackDepth < 0)
+ throw new IllegalArgumentException("The stack frame is not null, but the " +
+ "stack depth is less than zero.");
+ this.stackDepth = stackDepth;
+ this.stackFrame = stackFrame;
+ }
+
+ /**
+ *
+ *
+ * Name Type
+ *
+ * className java.lang.String
+ * identityHashCode java.lang.Integer
+ * lockedStackDepth java.lang.Integer
+ * lockedStackFrame javax.management.openmbean.CompositeData
+ *
+ *
+ *
+ * @param data the composite data structure to take values from.
+ * @return a new instance containing the values from the
+ * composite data structure, or Name Type
+ *
+ * className java.lang.String
+ * methodName java.lang.String
+ * fileName java.lang.String
+ * lineNumber java.lang.Integer
+ * nativeMethod java.lang.Boolean null
+ * if the data structure was also null
.
+ * @throws IllegalArgumentException if the composite data structure
+ * does not match the structure
+ * outlined above.
+ */
+ public static MonitorInfo from(CompositeData data)
+ {
+ if (data == null)
+ return null;
+ CompositeType type = data.getCompositeType();
+ ThreadInfo.checkAttribute(type, "ClassName", SimpleType.STRING);
+ ThreadInfo.checkAttribute(type, "IdentityHashCode", SimpleType.INTEGER);
+ ThreadInfo.checkAttribute(type, "LockedStackDepth", SimpleType.INTEGER);
+ ThreadInfo.checkAttribute(type, "LockedStackFrame",
+ ThreadInfo.getStackTraceType());
+ CompositeData frame = (CompositeData) data.get("LockedStackFrame");
+ return new MonitorInfo((String) data.get("ClassName"),
+ (Integer) data.get("IdentityHashCode"),
+ (Integer) data.get("LockedStackDepth"),
+ new StackTraceElement((String) frame.get("ClassName"),
+ (String) frame.get("MethodName"),
+ (String) frame.get("FileName"),
+ (Integer) frame.get("LineNumber")));
+ }
+
+ /**
+ * Returns the depth of the stack at which the lock was obtained.
+ * This works as an index into the array returned by
+ * {@link ThreadInfo#getStackTrace()}.
+ *
+ * @return the depth of the stack at which the lock was obtained,
+ * or a negative number if this information is unavailable.
+ */
+ public int getLockedStackDepth()
+ {
+ return stackDepth;
+ }
+
+ /**
+ * Returns the stack frame at which the lock was obtained.
+ *
+ * @return the stack frame at which the lock was obtained,
+ * or null
if this informati0on is unavailable.
+ */
+ public StackTraceElement getLockedStackFrame()
+ {
+ return stackFrame;
+ }
+
+}
diff --git a/libjava/classpath/java/lang/management/OperatingSystemMXBean.java b/libjava/classpath/java/lang/management/OperatingSystemMXBean.java
index 2430a9f..ed38285 100644
--- a/libjava/classpath/java/lang/management/OperatingSystemMXBean.java
+++ b/libjava/classpath/java/lang/management/OperatingSystemMXBean.java
@@ -87,6 +87,22 @@ public interface OperatingSystemMXBean
String getName();
/**
+ * Returns the system load average for the last minute, or -1
+ * if this is unavailable. The availability and calculation
+ * of the load average is system-dependent, but is usually
+ * a damped time-dependent average obtained by monitoring the
+ * number of queued and running processes. It is expected
+ * that this method will be called frequently to monitor the
+ * average over time, so it may not be implemented on systems
+ * where such a call is expensive.
+ *
+ * @return the system load average for the last minute, or -1
+ * if this is unavailable.
+ * @since 1.6
+ */
+ double getSystemLoadAverage();
+
+ /**
* Returns the version of the underlying operating system. This
* is equivalent to obtaining the os.version
property
* via {@link System#getProperty(String)}.
diff --git a/libjava/classpath/java/lang/management/ThreadInfo.java b/libjava/classpath/java/lang/management/ThreadInfo.java
index 428aca3..884f5af 100644
--- a/libjava/classpath/java/lang/management/ThreadInfo.java
+++ b/libjava/classpath/java/lang/management/ThreadInfo.java
@@ -37,6 +37,8 @@ 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;
@@ -68,6 +70,8 @@ import javax.management.openmbean.SimpleType;
* monitor, upon which the thread described here is blocked.
*
@@ -165,11 +169,28 @@ public class ThreadInfo
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 specified.
*
@@ -200,13 +221,57 @@ public class ThreadInfo
long waitedTime, boolean isInNative, boolean isSuspended,
StackTraceElement[] trace)
{
+ this(thread, blockedCount, blockedTime, lock, lockOwner, waitedCount,
+ waitedTime, isInNative, isSuspended, trace, new MonitorInfo[]{},
+ new LockInfo[]{});
+ }
+
+ /**
+ * Constructs a new {@link ThreadInfo} corresponding
+ * to the thread specified.
+ *
+ * @param thread the thread on which the 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 lock the monitor lock the thread is waiting for
+ * (only used if blocked)
+ * @param lockOwner the thread which owns the monitor lock, or
+ *
null
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(Thread thread, long blockedCount, long blockedTime,
+ Object lock, Thread lockOwner, long waitedCount,
+ long waitedTime, boolean isInNative, boolean isSuspended,
+ StackTraceElement[] trace, MonitorInfo[] lockedMonitors,
+ LockInfo[] lockedSynchronizers)
+ {
this(thread.getId(), thread.getName(), thread.getState(), blockedCount, blockedTime,
lock == null ? null : lock.getClass().getName() + "@" +
Integer.toHexString(System.identityHashCode(lock)),
lockOwner == null ? -1 : lockOwner.getId(),
lockOwner == null ? null : lockOwner.getName(),
waitedCount, waitedTime, isInNative, isSuspended,
- trace);
+ trace, lockedMonitors, lockedSynchronizers);
}
/**
@@ -248,6 +313,59 @@ public class ThreadInfo
long waitedTime, boolean isInNative, boolean isSuspended,
StackTraceElement[] trace)
{
+ this(threadId, threadName, threadState, blockedCount, blockedTime,
+ lockName, lockOwnerId, lockOwnerName, waitedCount, waitedTime,
+ isInNative, isSuspended, trace, new MonitorInfo[]{}, new LockInfo[]{});
+ }
+
+ /**
+ * 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 -1
if it doesn't have an owner
+ * (only used if blocked)
+ * @param lockOwnerName the name of the thread which owns the monitor
+ * lock, or null
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;
@@ -261,6 +379,8 @@ public class ThreadInfo
this.isInNative = isInNative;
this.isSuspended = isSuspended;
this.trace = trace;
+ this.lockedMonitors = lockedMonitors;
+ this.lockedSynchronizers = lockedSynchronizers;
}
/**
@@ -287,6 +407,44 @@ public class ThreadInfo
}
/**
+ * 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;
+ }
+
+ /**
* null
.
+ *
+ *
+ *
+ * @return a {@link LockInfo} object representing the lock on
+ * which the thread is blocked, or BLOCKED
state
+ * waiting to acquire an object monitor in order to enter
+ * a synchronized method or block.WAITING
or
+ * TIMED_WAITING
state due to a call to
+ * {@link java.lang.Object#wait()}.WAITING
or
+ * TIMED_WAITING
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()}.null
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)));
+ }
+
+ /**
* null
.
* Integer.toHexString(System.identityHashCode(l))
.
* The value is only unique to the extent that the identity
- * hash code is also unique.
+ * hash code is also unique. The value is the same as would
+ * be returned by getLockInfo().toString()
*
+ * Returns true if the thread is in a blocked state. + * The thread is regarded as blocked if: + *
+ *BLOCKED
state
+ * waiting to acquire an object monitor in order to enter
+ * a synchronized method or block.WAITING
or
+ * TIMED_WAITING
state due to a call to
+ * {@link java.lang.Object#wait()}.WAITING
or
+ * TIMED_WAITING
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()}.* This bean supports some optional behaviour, which all * virtual machines may not choose to implement. Specifically, - * this includes the monitoring of the CPU time used by a - * thread, and the monitoring of thread contention. The former - * is further subdivided into the monitoring of either just - * the current thread or all threads. The methods + * this includes the monitoring of: + *
+ *+ * The monitoring of CPU time is further subdivided into + * the monitoring of either just the current thread or all + * threads. The methods * {@link #isThreadCpuTimeSupported()}, - * {@link #isCurrentThreadCpuTimeSupported()} and - * {@link #isThreadContentionMonitoringSupported()} may be + * {@link #isCurrentThreadCpuTimeSupported()} + * {@link #isThreadContentionMonitoringSupported()}, + * {@link #isObjectMonitorUsageSupported()} and + * {@link #isSynchronizerUsageSupported()} may be * used to determine whether or not this functionality is * supported. *
*- * Furthermore, both these facilities may be disabled. - * In fact, thread contention monitoring is disabled by - * default, and must be explictly turned on by calling + * Furthermore, both time and contention monitoring may be + * disabled. In fact, thread contention monitoring is disabled + * by default, and must be explictly turned on by calling * the {@link #setThreadContentionMonitoringEnabled(boolean)} * method. *
@@ -82,6 +92,70 @@ public interface ThreadMXBean { /** + * This method returns information on all live threads at the + * time of execution (some threads may have terminated by the + * time the method completes). This method is simply a shorthand + * for calling {@link #getThreadInfo(long[], boolean, + * boolean)} with the return value of {@link #getAllThreadIds()}. + * + * @param lockedMonitors true if the returned {@link ThreadInfo} + * objects should contain information on + * locked monitors. + * @param lockedSynchronizers true if the returned {@link ThreadInfo} + * objects should contain information + * on locked ownable synchronizers. + * @return an array of {@link ThreadInfo} objects for all live threads. + * @throws SecurityException if a security manager exists and + * denies ManagementPermission("monitor"). + * @throws UnsupportedOperationException iflockedMonitors
+ * is true, but object monitor
+ * usage monitoring is not supported
+ * by the VM, or
+ * lockedSynchronizers
+ * is true, but ownable synchronizer
+ * usage monitoring is not supported
+ * by the VM.
+ * @since 1.6
+ * @see #getThreadInfo(long[], boolean, boolean)
+ * @see #getAllThreadIds()
+ * @see #isObjectMonitorUsageSupported()
+ * @see #isSynchronizerUsageSupported()
+ */
+ ThreadInfo[] dumpAllThreads(boolean lockedMonitors,
+ boolean lockedSynchronizers);
+
+ /**
+ * + * This method obtains a list of threads which are deadlocked + * waiting to obtain monitor or ownable synchronizer ownership. + * This is similar to the behaviour described for + * {@link #getMonitorDeadlockedThreads()}, except this method also + * takes in to account deadlocks involving ownable synchronizers. + *
+ *+ * Note that this method is not designed for controlling + * synchronization, but for troubleshooting problems which cause such + * deadlocks; it may be prohibitively expensive to use in normal + * operation. If only deadlocks involving monitors are of interest, + * then {@link #findMonitorDeadlockedThreads()} should be used in + * preference to this method. + *
+ * + * @return an array of thread identifiers, corresponding to threads + * which are currently in a deadlocked situation, or + *null
if there are no deadlocks.
+ * @throws SecurityException if a security manager exists and
+ * denies ManagementPermission("monitor").
+ * @throws UnsupportedOperationException if the VM does not support
+ * the monitoring of ownable
+ * synchronizer usage.
+ * @since 1.6
+ * @see #findMonitorDeadlockedThreads()
+ * @see #isSynchronizerUsageSupported()
+ */
+ long[] findDeadlockedThreads();
+
+ /**
* * This method obtains a list of threads which are deadlocked * waiting to obtain monitor ownership. On entering a synchronized @@ -115,13 +189,17 @@ public interface ThreadMXBean * of A and B. Note that this method is not designed for controlling * synchronization, but for troubleshooting problems which cause such * deadlocks; it may be prohibitively expensive to use in normal - * operation. + * operation. This method only returns deadlocks involving monitors; + * to include deadlocks involving ownable synchronizers, + * {@link #findDeadlockedThreads()} should be used instead. *
* * @return an array of thread identifiers, corresponding to threads - * which are currently in a deadlocked situation. + * which are currently in a deadlocked situation, or + *null
if there are no deadlocks.
* @throws SecurityException if a security manager exists and
* denies ManagementPermission("monitor").
+ * @see #findDeadlockedThreads()
*/
long[] findMonitorDeadlockedThreads();
@@ -285,6 +363,53 @@ public interface ThreadMXBean
ThreadInfo[] getThreadInfo(long[] ids);
/**
+ * Returns information on the specified threads with full
+ * stack trace information and optional synchronization
+ * information. If lockedMonitors
is false,
+ * or there are no locked monitors for a particular thread,
+ * then the corresponding {@link ThreadInfo} object will have
+ * an empty {@link MonitorInfo} array. Likewise, if
+ * lockedSynchronizers
is false, or there are
+ * no locked ownable synchronizers for a particular thread,
+ * then the corresponding {@link ThreadInfo} object will have
+ * an empty {@link LockInfo} array. If both
+ * lockedMonitors
and lockedSynchronizers
+ * are false, the return value is equivalent to that from
+ * {@link #getThreadInfo}(ids, Integer.MAX_VALUE)
.
+ * If an identifier specifies a thread which is either non-existant
+ * or not alive, then the corresponding element in the returned
+ * array is null
.
+ *
+ * @param ids an array of thread identifiers to return information
+ * on.
+ * @param lockedMonitors true if information on locked monitors
+ * should be included.
+ * @param lockedSynchronizers true if information on locked
+ * ownable synchronizers should be included.
+ * @return an array of {@link ThreadInfo} objects matching the
+ * specified threads. The corresponding element is
+ * null
if the identifier specifies
+ * a thread that doesn't exist or is not alive.
+ * @throws IllegalArgumentException if an identifier in the array is
+ * <= 0.
+ * @throws SecurityException if a security manager exists and
+ * denies ManagementPermission("monitor").
+ * @throws UnsupportedOperationException if lockedMonitors
+ * is true, but object monitor
+ * usage monitoring is not supported
+ * by the VM, or
+ * lockedSynchronizers
+ * is true, but ownable synchronizer
+ * usage monitoring is not supported
+ * by the VM.
+ * @since 1.6
+ * @see #isObjectMonitorUsageSupported()
+ * @see #isSynchronizerUsageSupported()
+ */
+ ThreadInfo[] getThreadInfo(long[] ids, boolean lockedMonitors,
+ boolean lockedSynchronizers);
+
+ /**
* Returns information on the specified thread with
* stack trace information to the supplied depth. If the
* identifier specifies a thread which is either non-existant
@@ -390,6 +515,26 @@ public interface ThreadMXBean
boolean isCurrentThreadCpuTimeSupported();
/**
+ * Returns true if the virtual machine supports the monitoring
+ * of object monitor usage.
+ *
+ * @return true if the monitoring of object monitor usage
+ * is supported by the virtual machine.
+ * @since 1.6
+ */
+ boolean isObjectMonitorUsageSupported();
+
+ /**
+ * Returns true if the virtual machine supports the monitoring
+ * of ownable synchronizer usage.
+ *
+ * @return true if the monitoring of ownable synchronizer usage
+ * is supported by the virtual machine.
+ * @since 1.6
+ */
+ boolean isSynchronizerUsageSupported();
+
+ /**
* Returns true if thread contention monitoring is currently
* enabled.
*
--
cgit v1.1