JDK-8185705 : JMX: Add a version of ThreadMXBean.dumpAllThreads with a maxDepth argument
  • Type: CSR
  • Component: core-svc
  • Sub-Component: java.lang.management
  • Priority: P4
  • Status: Closed
  • Resolution: Approved
  • Fix Versions: 10
  • Submitted: 2017-08-02
  • Updated: 2017-09-18
  • Resolved: 2017-09-18
Related Reports
CSR :  
Description
Summary
-------

Currently `java.lang.management.ThreadMXBean.dumpAllThreads` and a version of `java.lang.management.ThreadMXBean.getThreadInfo` which includes `lockedMonitors` and `lockedSynchronizers` parameter but can't restrict the stack trace depth as can other versions of `java.lang.management.ThreadMXBean.getThreadInfo`.

Introduced two new API's `java.lang.management.ThreadMXBean.dumpAllThreads` and `java.lang.management.ThreadMXBean.getThreadInfo` with `maxDepth` argument to limit the stack trace depth.

Updated the javadoc of `getThreadInfo(ids, lockedMonitors, lockedSynchronizers)` and `dumpAllThreads(lockedMonitors, lockedSynchronizers)`

Problem
-------

`java.lang.management.ThreadMXBean.dumpAllThreads` currently cannot limit returned stack trace depth. 
`java.lang.management.ThreadMXBean.dumpAllThreads` can therefore take excessive time/space for programs with thousands of threads.

Solution
--------

Introducing two new API's `java.lang.management.ThreadMXBean.dumpAllThreads` and `java.lang.management.ThreadMXBean.getThreadInfo` with `maxDepth` argument to limit the stack trace depth.


Specification
-------------

       Two new methods were introduced 
     
         /**
         * Returns the thread info for each thread whose ID
         * is in the input array {@code ids},
         * with stack trace of the specified maximum number of elements
         * and synchronization information.
         * If {@code maxDepth == 0}, no stack trace of the thread
         * will be dumped.
         *
         * <p>
         * This method obtains a snapshot of the thread information
         * for each thread including:
         * <ul>
         *    <li>stack trace of the specified maximum number of elements,</li>
         *    <li>the object monitors currently locked by the thread
         *        if {@code lockedMonitors} is {@code true}, and</li>
         *    <li>the <a href="LockInfo.html#OwnableSynchronizer">
         *        ownable synchronizers</a> currently locked by the thread
         *        if {@code lockedSynchronizers} is {@code true}.</li>
         * </ul>
         * <p>
         * This method returns an array of the {@code ThreadInfo} objects,
         * each is the thread information about the thread with the same index
         * as in the {@code ids} array.
         * If a thread of the given ID is not alive or does not exist,
         * {@code null} will be set in the corresponding element
         * in the returned array.  A thread is alive if
         * it has been started and has not yet died.
         * <p>
         * If a thread does not lock any object monitor or {@code lockedMonitors}
         * is {@code false}, the returned {@code ThreadInfo} object will have an
         * empty {@code MonitorInfo} array.  Similarly, if a thread does not
         * lock any synchronizer or {@code lockedSynchronizers} is {@code false},
         * the returned {@code ThreadInfo} object
         * will have an empty {@code LockInfo} array.
         *
         * <p>
         * When both {@code lockedMonitors} and {@code lockedSynchronizers}
         * parameters are {@code false}, it is equivalent to calling:
         * <blockquote><pre>
         *     {@link #getThreadInfo(long[], int)  getThreadInfo(ids, maxDepth)}
         * </pre></blockquote>
         *
         * <p>
         * This method is designed for troubleshooting use, but not for
         * synchronization control.  It might be an expensive operation.
         *
         * <p>
         * <b>MBeanServer access</b>:<br>
         * The mapped type of {@code ThreadInfo} is
         * {@code CompositeData} with attributes as specified in the
         * {@link ThreadInfo#from ThreadInfo.from} method.
         *
         * @implSpec The default implementation throws
         * {@code UnsupportedOperationException}.
         *
         * @param  ids an array of thread IDs.
         * @param  lockedMonitors if {@code true}, retrieves all locked monitors.
         * @param  lockedSynchronizers if {@code true}, retrieves all locked
         *             ownable synchronizers.
         * @param  maxDepth indicates the maximum number of
         * {@link StackTraceElement} to be retrieved from the stack trace.
         *
         * @return an array of the {@link ThreadInfo} objects, each containing
         * information about a thread whose ID is in the corresponding
         * element of the input array of IDs.
         *
         * @throws IllegalArgumentException if {@code maxDepth} is negative.
         * @throws java.lang.SecurityException if a security manager
         *         exists and the caller does not have
         *         ManagementPermission("monitor").
         * @throws java.lang.UnsupportedOperationException
         *         <ul>
         *           <li>if {@code lockedMonitors} is {@code true} but
         *               the Java virtual machine does not support monitoring
         *               of {@linkplain #isObjectMonitorUsageSupported
         *               object monitor usage}; or</li>
         *           <li>if {@code lockedSynchronizers} is {@code true} but
         *               the Java virtual machine does not support monitoring
         *               of {@linkplain #isSynchronizerUsageSupported
         *               ownable synchronizer usage}.</li>
         *         </ul>
         *
         * @see #isObjectMonitorUsageSupported
         * @see #isSynchronizerUsageSupported
         *
         * @since 10
         */
    
        public default ThreadInfo[] getThreadInfo(long[] ids, boolean lockedMonitors,
                                                  boolean lockedSynchronizers, int maxDepth) {
            throw new UnsupportedOperationException();
        }
    
     /**
         * Returns the thread info for all live threads
         * with stack trace of the specified maximum number of elements
         * and synchronization information.
         * If {@code maxDepth == 0}, no stack trace of the thread
         * will be dumped.
         * Some threads included in the returned array
         * may have been terminated when this method returns.
         *
         * <p>
         * This method returns an array of {@link ThreadInfo} objects
         * as specified in the {@link #getThreadInfo(long[], boolean, boolean, int)}
         * method.
         *
         * @implSpec The default implementation throws
         * {@code UnsupportedOperationException}.
         *
         * @param  lockedMonitors if {@code true}, dump all locked monitors.
         * @param  lockedSynchronizers if {@code true}, dump all locked
         *             ownable synchronizers.
         * @param  maxDepth indicates the maximum number of
         * {@link StackTraceElement} to be retrieved from the stack trace.
         *
         * @return an array of {@link ThreadInfo} for all live threads.
         *
         * @throws IllegalArgumentException if {@code maxDepth} is negative.
         * @throws java.lang.SecurityException if a security manager
         *         exists and the caller does not have
         *         ManagementPermission("monitor").
         * @throws java.lang.UnsupportedOperationException
         *         <ul>
         *           <li>if {@code lockedMonitors} is {@code true} but
         *               the Java virtual machine does not support monitoring
         *               of {@linkplain #isObjectMonitorUsageSupported
         *               object monitor usage}; or</li>
         *           <li>if {@code lockedSynchronizers} is {@code true} but
         *               the Java virtual machine does not support monitoring
         *               of {@linkplain #isSynchronizerUsageSupported
         *               ownable synchronizer usage}.</li>
         *         </ul>
         *
         * @see #isObjectMonitorUsageSupported
         * @see #isSynchronizerUsageSupported
         *
         * @since 10
         */
        public default ThreadInfo[] dumpAllThreads(boolean lockedMonitors,
                                                   boolean lockedSynchronizers, int maxDepth) {
            throw new UnsupportedOperationException();
        }
    }
    
    javadoc of the two existing methods is updated to say that it is equivalent to calling
    
    'getThreadInfo(ids, lockedMonitors, lockedSynchronizers, Integer.MAX_VALUE)'
    and
    'dumpAllThreads(lockedMonitors, lockedSynchronizers, Integer.MAX_VALUE)'
    
    diff for the updated javadoc
    
         /**
          * Returns the thread info for each thread
    -     * whose ID is in the input array {@code ids}, with stack trace
    -     * and synchronization information.
    -     *
    -     * <p>
    -     * This method obtains a snapshot of the thread information
    -     * for each thread including:
    -     * <ul>
    -     *    <li>the entire stack trace,</li>
    -     *    <li>the object monitors currently locked by the thread
    -     *        if {@code lockedMonitors} is {@code true}, and</li>
    -     *    <li>the <a href="LockInfo.html#OwnableSynchronizer">
    -     *        ownable synchronizers</a> currently locked by the thread
    -     *        if {@code lockedSynchronizers} is {@code true}.</li>
    -     * </ul>
    -     * <p>
    -     * This method returns an array of the {@code ThreadInfo} objects,
    -     * each is the thread information about the thread with the same index
    -     * as in the {@code ids} array.
    -     * If a thread of the given ID is not alive or does not exist,
    -     * {@code null} will be set in the corresponding element
    -     * in the returned array.  A thread is alive if
    -     * it has been started and has not yet died.
    -     * <p>
    -     * If a thread does not lock any object monitor or {@code lockedMonitors}
    -     * is {@code false}, the returned {@code ThreadInfo} object will have an
    -     * empty {@code MonitorInfo} array.  Similarly, if a thread does not
    -     * lock any synchronizer or {@code lockedSynchronizers} is {@code false},
    -     * the returned {@code ThreadInfo} object
    -     * will have an empty {@code LockInfo} array.
    -     *
    -     * <p>
    -     * When both {@code lockedMonitors} and {@code lockedSynchronizers}
    -     * parameters are {@code false}, it is equivalent to calling:
    -     * <blockquote><pre>
    -     *     {@link #getThreadInfo(long[], int)  getThreadInfo(ids, Integer.MAX_VALUE)}
    -     * </pre></blockquote>
    -     *
    -     * <p>
    -     * This method is designed for troubleshooting use, but not for
    -     * synchronization control.  It might be an expensive operation.
    -     *
    -     * <p>
    -     * <b>MBeanServer access</b>:<br>
    -     * The mapped type of {@code ThreadInfo} is
    -     * {@code CompositeData} with attributes as specified in the
    -     * {@link ThreadInfo#from ThreadInfo.from} method.
    +     * whose ID is in the input array {@code ids},
    +     * with stack trace and synchronization information.
    +     * This is equivalent to calling:
    +     * <blockquote>
    +     * {@link #getThreadInfo(long[], boolean, boolean, int)
    +     * getThreadInfo(ids, lockedMonitors, lockedSynchronizers, Integer.MAX_VALUE)}
    +     * </blockquote>
          *
          * @param  ids an array of thread IDs.
          * @param  lockedMonitors if {@code true}, retrieves all locked monitors.
          *
          * @since 1.6
          */
    -    public ThreadInfo[] getThreadInfo(long[] ids, boolean lockedMonitors, boolean lockedSynchronizers);
    +    public ThreadInfo[] getThreadInfo(long[] ids, boolean lockedMonitors,
    +                                      boolean lockedSynchronizers);
     
     
         /**
          * Returns the thread info for all live threads with stack trace
          * and synchronization information.
    -     * Some threads included in the returned array
    -     * may have been terminated when this method returns.
    -     *
    -     * <p>
    -     * This method returns an array of {@link ThreadInfo} objects
    -     * as specified in the {@link #getThreadInfo(long[], boolean, boolean)}
    -     * method.
    +     * This is equivalent to calling:
    +     * <blockquote>
    +     * {@link #dumpAllThreads(boolean, boolean, int)
    +     * dumpAllThreads(lockedMonitors, lockedSynchronizers, Integer.MAX_VALUE)}
    +     * </blockquote>
          *
          * @param  lockedMonitors if {@code true}, dump all locked monitors.
          * @param  lockedSynchronizers if {@code true}, dump all locked


Comments
Moving to approved.
18-09-2017

Kindly inform if current version looks good or it requires any changes.
15-09-2017

updated as suggested
13-09-2017

@Ujwal, please update the proposed specification to make this case explicit. Thanks.
13-09-2017

stack trace won't be dumped(stack trace depth will be 0). other thread information excluding stack trace will be returned���.
13-09-2017

What is the expected behavior if maxDepth is 0?
13-09-2017

Made changes as suggested. Please check if current version is as expected.
12-09-2017

Please rephrase the summary so it is a summary of what is changing. Please explicitly state which package the new methods are being added; the platform includes both java.lang.management.ThreadMXBean and com.sun.management.ThreadMXBean.
06-09-2017