This updates the threading bean and ThreadInfo class to 1.6 level. Culmulatively, this means that there is now optional support for the monitoring of object monitor and ownable synchronizer locks. VMs supporting the current 1.5 state of affairs should still work without problems (although some may need to add stubs for the new methods, depending on how the bean classes are used); please let me know if this is not the case. Support is enabled by implementing the new methods and providing the associated properties as documented in the VM guide.
Changelog:
2006-12-25 Andrew John Hughes <[EMAIL PROTECTED]>
* doc/vmintegration.texinfo:
Updated to match new threading bean API.
* gnu/java/lang/management/ThreadMXBeanImpl.java:
(MONITOR_SUPPORT): New constant for object monitor
lock support property.
(SYNCHRONIZER_SUPPORT): New constant for ownable
synchronizer lock support property.
(dumpAllThreads(boolean,boolean)): Implemented.
(findDeadlockedThreads()): Likewise.
(getThreadInfo(long[],boolean,boolean)): Likewise.
(isObjectMonitorUsageSupported()): Likewise.
(isSynchronizerUsageSupported()): Likewise.
* java/lang/management/ThreadInfo.java:
(ThreadInfo(Thread,long,long,Object,Thread,long,
long,boolean,boolean,StackTraceElement[],
MonitorInfo[], LockInfo[])): New constructor.
(ThreadInfo(long,String,Thread.State,long,long,
String,long,String,long,long,boolean,boolean,
StackTraceElement[],MonitorInfo[], LockInfo[])):
Likewise.
(from(CompositeData)): Updated to handle new attributes.
(getLockedMonitors()): Implemented.
(getLockedSynchronizers()): Likewise.
(getLockInfo()): Likewise.
(getLockName()): Handle blocking as documented in 1.6
(getLockOwnerId()): Likewise.
(getLockOwnerName()): Likewise.
(toString()): Likewise.
(isThreadBlocked()): Thread blocked check based on
documented 1.6 semantics.
* java/lang/management/ThreadMXBean.java:
(dumpAllThreads(boolean,boolean)): Implemented.
(findDeadlockedThreads()): Likewise.
(getThreadInfo(long[],boolean,boolean)): Likewise.
(isObjectMonitorUsageSupported()): Likewise.
(isSynchronizerUsageSupported()): Likewise.
* vm/reference/gnu/java/lang/management/VMThreadMXBeanImpl.java:
(findDeadlockedThreads()): New native method.
(getLockInfo(ThreadInfo)): Likewise.
(getMonitorInfo(ThreadInfo)): Likewise.
--
Andrew :-)
Escape the Java Trap with GNU Classpath!
http://www.gnu.org/philosophy/java-trap.html
public class gcj extends Freedom implements Java { ... }
Index: doc/vmintegration.texinfo
===================================================================
RCS file: /cvsroot/classpath/classpath/doc/vmintegration.texinfo,v
retrieving revision 1.41
diff -u -3 -p -u -r1.41 vmintegration.texinfo
--- doc/vmintegration.texinfo 26 Nov 2006 14:33:13 -0000 1.41
+++ doc/vmintegration.texinfo 25 Dec 2006 23:47:48 -0000
@@ -1376,6 +1376,12 @@ time used by all threads.
@item @code{gnu.java.lang.management.ThreadContentionSupport} --
This property should be present if the VM supports thread contention
monitoring.
[EMAIL PROTECTED] @code{gnu.java.lang.management.MonitorUsageMonitoringSupport}
--
+This property should be present if the VM supports the monitoring
+of object monitor usage.
[EMAIL PROTECTED]
@code{gnu.java.lang.management.OwnableSynchronizerUsageMonitoringSupport} --
+This property should be present if the VM supports the monitoring
+of ownable synchronizer usage.
@end itemize
In addition, the property
@@ -1386,11 +1392,18 @@ is enabled at startup.
The methods are as follows:
@itemize @bullet
[EMAIL PROTECTED] @code{(findDeadlockedThreads())} -- This should return
+an array of thread identifiers which match threads involved in
+deadlock cycles (where each thread is waiting to obtain a lock
+held by one of the others) on object monitors or ownable
+synchronizers. This is specified as a native method in the
+reference implementation, and is optional. It is only called
+when the VM supports ownable synchronizer monitoring.
@item @code{(findMonitorDeadlockedThreads())} -- This should return
an array of thread identifiers which match threads involved in
deadlock cycles (where each thread is waiting to obtain a lock
-held by one of the others). This is specified as a native method
-in the reference implementation.
+held by one of the others) on object monitors. This is specified
+as a native method in the reference implementation.
@item @code{(getAllThreads())} -- This should return an array of
all live threads and set the @code{filled} variable to the number
found. A default implementation is provided.
@@ -1408,6 +1421,16 @@ supporting time monitoring.
@item @code{(getDaemonThreadCount())} -- This should return the number
of live daemon threads. A default implementation is provided, based
on @code{getAllThreads()}.
[EMAIL PROTECTED] @code{(getLockInfo(ThreadInfo))} -- This is an optional native
+method called when the VM supports ownable synchronizer usage monitoring
+and the user has requested information for a particular thread. The
+supplied @code{ThreadInfo} object should be filled out with an
+array of @code{LockInfo} objects, providing details on each lock.
[EMAIL PROTECTED] @code{(getMonitorInfo(ThreadInfo))} -- This is an optional
native
+method called when the VM supports object monitor usage monitoring
+and the user has requested information for a particular thread. The
+supplied @code{ThreadInfo} object should be filled out with an
+array of @code{MonitorInfo} objects, providing details on each lock.
@item @code{(getPeakThreadCount())} -- The VM should maintain a record
of the peak number of live threads, and return it when this method is
called. This is specified as a native method in the reference
Index: gnu/java/lang/management/ThreadMXBeanImpl.java
===================================================================
RCS file:
/cvsroot/classpath/classpath/gnu/java/lang/management/ThreadMXBeanImpl.java,v
retrieving revision 1.3
diff -u -3 -p -u -r1.3 ThreadMXBeanImpl.java
--- gnu/java/lang/management/ThreadMXBeanImpl.java 29 Jul 2006 14:05:59
-0000 1.3
+++ gnu/java/lang/management/ThreadMXBeanImpl.java 25 Dec 2006 23:47:50
-0000
@@ -83,7 +83,19 @@ public final class ThreadMXBeanImpl
*/
private static final String TIME_ENABLED =
"gnu.java.lang.management.ThreadTimeInitallyEnabled";
-
+
+ /**
+ * Constant for monitor usage monitoring support.
+ */
+ private static final String MONITOR_SUPPORT =
+ "gnu.java.lang.management.MonitorUsageMonitoringSupport";
+
+ /**
+ * Constant for ownable synchronizer usage monitoring support.
+ */
+ private static final String SYNCHRONIZER_SUPPORT =
+ "gnu.java.lang.management.OwnableSynchronizerUsageMonitoringSupport";
+
/**
* Flag to indicate whether time monitoring is enabled or not.
*/
@@ -112,6 +124,23 @@ public final class ThreadMXBeanImpl
contentionEnabled = false;
}
+ public ThreadInfo[] dumpAllThreads(boolean lockedMonitors,
+ boolean lockedSynchronizers)
+ {
+ return getThreadInfo(getAllThreadIds(), lockedMonitors,
+ lockedSynchronizers);
+ }
+
+ public long[] findDeadlockedThreads()
+ {
+ checkMonitorPermissions();
+ if (!isSynchronizerUsageSupported())
+ throw new UnsupportedOperationException("Ownable synchronizer usage " +
+ "monitoring is not provided " +
+ "by this VM.");
+ return VMThreadMXBeanImpl.findDeadlockedThreads();
+ }
+
public long[] findMonitorDeadlockedThreads()
{
checkMonitorPermissions();
@@ -207,6 +236,27 @@ public final class ThreadMXBeanImpl
return infos;
}
+ public ThreadInfo[] getThreadInfo(long[] ids, boolean lockedMonitors,
+ boolean lockedSynchronizers)
+ {
+ checkMonitorPermissions();
+ if (lockedMonitors && !isObjectMonitorUsageSupported())
+ throw new UnsupportedOperationException("Monitor usage monitoring is " +
+ "not provided by this VM.");
+ if (lockedSynchronizers && !isSynchronizerUsageSupported())
+ throw new UnsupportedOperationException("Ownable synchronizer usage " +
+ "monitoring is not provided " +
+ "by this VM.");
+ ThreadInfo[] infos = getThreadInfo(ids, Integer.MAX_VALUE);
+ if (lockedMonitors)
+ for (ThreadInfo info : infos)
+ VMThreadMXBeanImpl.getMonitorInfo(info);
+ if (lockedSynchronizers)
+ for (ThreadInfo info : infos)
+ VMThreadMXBeanImpl.getLockInfo(info);
+ return infos;
+ }
+
public long getThreadUserTime(long id)
{
if (!isThreadCpuTimeSupported())
@@ -231,6 +281,16 @@ public final class ThreadMXBeanImpl
return SystemProperties.getProperty(CURRENT_THREAD_TIME_SUPPORT) != null;
}
+ public boolean isObjectMonitorUsageSupported()
+ {
+ return SystemProperties.getProperty(MONITOR_SUPPORT) != null;
+ }
+
+ public boolean isSynchronizerUsageSupported()
+ {
+ return SystemProperties.getProperty(SYNCHRONIZER_SUPPORT) != null;
+ }
+
public boolean isThreadContentionMonitoringEnabled()
{
if (isThreadContentionMonitoringSupported())
Index: java/lang/management/ThreadInfo.java
===================================================================
RCS file: /cvsroot/classpath/classpath/java/lang/management/ThreadInfo.java,v
retrieving revision 1.8
diff -u -3 -p -u -r1.8 ThreadInfo.java
--- java/lang/management/ThreadInfo.java 25 Dec 2006 01:40:29 -0000
1.8
+++ java/lang/management/ThreadInfo.java 25 Dec 2006 23:47:51 -0000
@@ -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.Simple
* 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>
@@ -165,6 +169,17 @@ 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;
@@ -206,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 [EMAIL PROTECTED] 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
+ * <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 [EMAIL PROTECTED] MonitorInfo} objects
+ * representing locks held on object monitors
+ * by the thread.
+ * @param lockedSynchronizers an array of [EMAIL PROTECTED] 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);
}
/**
@@ -254,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 [EMAIL PROTECTED] 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 [EMAIL PROTECTED] MonitorInfo} objects
+ * representing locks held on object monitors
+ * by the thread.
+ * @param lockedSynchronizers an array of [EMAIL PROTECTED] 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;
@@ -267,6 +379,8 @@ public class ThreadInfo
this.isInNative = isInNative;
this.isSuspended = isSuspended;
this.trace = trace;
+ this.lockedMonitors = lockedMonitors;
+ this.lockedSynchronizers = lockedSynchronizers;
}
/**
@@ -403,6 +517,65 @@ public class ThreadInfo
"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)
@@ -414,6 +587,27 @@ public class ThreadInfo
(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")),
@@ -426,7 +620,7 @@ public class ThreadInfo
((Long) data.get("WaitedTime")).longValue(),
((Boolean) data.get("InNative")).booleanValue(),
((Boolean) data.get("Suspended")).booleanValue(),
- traces);
+ traces, mInfo, lInfo);
}
/**
@@ -486,9 +680,74 @@ public class ThreadInfo
}
/**
+ * Returns an array of [EMAIL PROTECTED] 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 [EMAIL PROTECTED] 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 [EMAIL PROTECTED] 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 [EMAIL PROTECTED] 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 [EMAIL PROTECTED] 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
+ * [EMAIL PROTECTED] 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 [EMAIL PROTECTED] java.util.concurrent.locks.LockSupport#park()}.
+ * The lock is the return value of
+ * [EMAIL PROTECTED]
java.util.concurrent.locks.LockSupport#getBlocker()}.</li>
+ * </ol>
+ *
+ * @return a [EMAIL PROTECTED] 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 [EMAIL PROTECTED] 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
* <code>null</code>.
* </p>
@@ -504,7 +763,8 @@ public class ThreadInfo
* and
* <code>Integer.toHexString(System.identityHashCode(l))</code>.
* 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 <code>getLockInfo().toString()</code>
* </p>
*
* @return a string representing the lock on which this
@@ -513,7 +773,7 @@ public class ThreadInfo
*/
public String getLockName()
{
- if (threadState != Thread.State.BLOCKED)
+ if (!isThreadBlocked())
return null;
return lockName;
}
@@ -531,7 +791,7 @@ public class ThreadInfo
*/
public long getLockOwnerId()
{
- if (threadState != Thread.State.BLOCKED)
+ if (!isThreadBlocked())
return -1;
return lockOwnerId;
}
@@ -549,7 +809,7 @@ public class ThreadInfo
*/
public String getLockOwnerName()
{
- if (threadState != Thread.State.BLOCKED)
+ if (!isThreadBlocked())
return null;
return lockOwnerName;
}
@@ -724,10 +984,40 @@ public class ThreadInfo
", waitedCount=" + waitedCount +
", isInNative=" + isInNative +
", isSuspended=" + isSuspended +
- (threadState == Thread.State.BLOCKED ?
+ (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
+ * [EMAIL PROTECTED] 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 [EMAIL PROTECTED] java.util.concurrent.locks.LockSupport#park()}.
+ * The lock is the return value of
+ * [EMAIL PROTECTED]
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);
+ }
+
}
Index: java/lang/management/ThreadMXBean.java
===================================================================
RCS file: /cvsroot/classpath/classpath/java/lang/management/ThreadMXBean.java,v
retrieving revision 1.3
diff -u -3 -p -u -r1.3 ThreadMXBean.java
--- java/lang/management/ThreadMXBean.java 1 Jul 2006 11:37:59 -0000
1.3
+++ java/lang/management/ThreadMXBean.java 25 Dec 2006 23:47:52 -0000
@@ -57,20 +57,30 @@ package java.lang.management;
* <p>
* 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:
+ * </p>
+ * <ul>
+ * <li>the CPU time used by a thread</li>
+ * <li>thread contention</li>
+ * <li>object monitor usage</li>
+ * <li>ownable synchronizer usage</li>
+ * </ul>
+ * <p>
+ * The monitoring of CPU time is further subdivided into
+ * the monitoring of either just the current thread or all
+ * threads. The methods
* [EMAIL PROTECTED] #isThreadCpuTimeSupported()},
- * [EMAIL PROTECTED] #isCurrentThreadCpuTimeSupported()} and
- * [EMAIL PROTECTED] #isThreadContentionMonitoringSupported()} may be
+ * [EMAIL PROTECTED] #isCurrentThreadCpuTimeSupported()}
+ * [EMAIL PROTECTED] #isThreadContentionMonitoringSupported()},
+ * [EMAIL PROTECTED] #isObjectMonitorUsageSupported()} and
+ * [EMAIL PROTECTED] #isSynchronizerUsageSupported()} may be
* used to determine whether or not this functionality is
* supported.
* </p>
* <p>
- * 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 [EMAIL PROTECTED] #setThreadContentionMonitoringEnabled(boolean)}
* method.
* </p>
@@ -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 [EMAIL PROTECTED] #getThreadInfo(long[], boolean,
+ * boolean)} with the return value of [EMAIL PROTECTED] #getAllThreadIds()}.
+ *
+ * @param lockedMonitors true if the returned [EMAIL PROTECTED] ThreadInfo}
+ * objects should contain information on
+ * locked monitors.
+ * @param lockedSynchronizers true if the returned [EMAIL PROTECTED]
ThreadInfo}
+ * objects should contain information
+ * on locked ownable synchronizers.
+ * @return an array of [EMAIL PROTECTED] ThreadInfo} objects for all live
threads.
+ * @throws SecurityException if a security manager exists and
+ * denies ManagementPermission("monitor").
+ * @throws UnsupportedOperationException if <code>lockedMonitors</code>
+ * is true, but object monitor
+ * usage monitoring is not supported
+ * by the VM, or
+ * <code>lockedSynchronizers</code>
+ * 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);
+
+ /**
+ * <p>
+ * 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
+ * [EMAIL PROTECTED] #getMonitorDeadlockedThreads()}, except this method also
+ * takes in to account deadlocks involving ownable synchronizers.
+ * </p>
+ * <p>
+ * 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 [EMAIL PROTECTED] #findMonitorDeadlockedThreads()} should be used in
+ * preference to this method.
+ * </p>
+ *
+ * @return an array of thread identifiers, corresponding to threads
+ * which are currently in a deadlocked situation, or
+ * <code>null</code> 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();
+
+ /**
* <p>
* 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,
+ * [EMAIL PROTECTED] #findDeadlockedThreads()} should be used instead.
* </p>
*
* @return an array of thread identifiers, corresponding to threads
- * which are currently in a deadlocked situation.
+ * which are currently in a deadlocked situation, or
+ * <code>null</code> 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 <code>lockedMonitors</code> is false,
+ * or there are no locked monitors for a particular thread,
+ * then the corresponding [EMAIL PROTECTED] ThreadInfo} object will have
+ * an empty [EMAIL PROTECTED] MonitorInfo} array. Likewise, if
+ * <code>lockedSynchronizers</code> is false, or there are
+ * no locked ownable synchronizers for a particular thread,
+ * then the corresponding [EMAIL PROTECTED] ThreadInfo} object will have
+ * an empty [EMAIL PROTECTED] LockInfo} array. If both
+ * <code>lockedMonitors</code> and <code>lockedSynchronizers</code>
+ * are false, the return value is equivalent to that from
+ * <code>[EMAIL PROTECTED] #getThreadInfo}(ids, Integer.MAX_VALUE)</code>.
+ * If an identifier specifies a thread which is either non-existant
+ * or not alive, then the corresponding element in the returned
+ * array is <code>null</code>.
+ *
+ * @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 [EMAIL PROTECTED] ThreadInfo} objects matching the
+ * specified threads. The corresponding element is
+ * <code>null</code> 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 <code>lockedMonitors</code>
+ * is true, but object monitor
+ * usage monitoring is not supported
+ * by the VM, or
+ * <code>lockedSynchronizers</code>
+ * 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.
*
Index: vm/reference/gnu/java/lang/management/VMThreadMXBeanImpl.java
===================================================================
RCS file:
/cvsroot/classpath/classpath/vm/reference/gnu/java/lang/management/VMThreadMXBeanImpl.java,v
retrieving revision 1.1
diff -u -3 -p -u -r1.1 VMThreadMXBeanImpl.java
--- vm/reference/gnu/java/lang/management/VMThreadMXBeanImpl.java 1 Jul
2006 11:37:59 -0000 1.1
+++ vm/reference/gnu/java/lang/management/VMThreadMXBeanImpl.java 25 Dec
2006 23:47:59 -0000
@@ -60,6 +60,16 @@ final class VMThreadMXBeanImpl
/**
* Returns the ids of cycles of deadlocked threads, occurring
+ * due to monitor ownership or ownable synchronizer ownership.
+ * This will only be called if ownable synchronizer monitoring
+ * is supported.
+ *
+ * @return the ids of the deadlocked threads.
+ */
+ static native long[] findDeadlockedThreads();
+
+ /**
+ * Returns the ids of cycles of deadlocked threads, occurring
* due to monitor ownership.
*
* @return the ids of the deadlocked threads.
@@ -138,6 +148,25 @@ final class VMThreadMXBeanImpl
}
/**
+ * Fill out the given [EMAIL PROTECTED] ThreadInfo} object
+ * with ownable synchronizer usage information.
+ * This is only called if ownable synchronizer
+ * usage monitoring is supported.
+ *
+ * @param info the [EMAIL PROTECTED] ThreadInfo} object to modify.
+ */
+ static native void getLockInfo(ThreadInfo info);
+
+ /**
+ * Fill out the given [EMAIL PROTECTED] ThreadInfo} object
+ * with monitor usage information. This is only
+ * called if monitor usage monitoring is supported.
+ *
+ * @param info the [EMAIL PROTECTED] ThreadInfo} object to modify.
+ */
+ static native void getMonitorInfo(ThreadInfo info);
+
+ /**
* Returns the current peak number of live threads.
*
* @return the peak number of live threads.
signature.asc
Description: Digital signature
