JDK-8251498 : 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: openjdk8u282
  • Submitted: 2020-08-12
  • Updated: 2020-09-23
  • Resolved: 2020-09-15
Related Reports
CSR :  
Relates :  
Description
This is an 8u backport CSR of https://bugs.openjdk.java.net/browse/JDK-8185705. The original CSR specified the addition of two methods to `java.lang.management.ThreadMXBean`, so cannot be applied directly to Java 8 without an approved Java 8 update JSR. That will not happen for this kind of change, so this CSR instead adds the two methods to `com.sun.management.ThreadMXBean`. The package `com.sun.management` is JDK-specific and thus outside the scope of the Java SE 8 specification.

Volker Simonis pointed out in https://mail.openjdk.java.net/pipermail/jdk8u-dev/2020-August/012557.html that when we backport a JMM feature, we are actually updating the existing JMM version specification rather than transitioning to a new one. There was a bit of recognition of this in https://bugs.openjdk.java.net/browse/JDK-8249101, where the @since javadoc tag was updated to 11.0.9 rather than 14. Imo, Volker makes a good argument for leaving the JMM version alone when doing JMM backports. So, we will

1. In both jmm.h files (jdk and hotspot), leave JMM_VERSION at 0x20010203.
2. Change the @since javadoc from '10' to '8u282'.

The original CSR updated the javadoc of the pre-existing DumpAllThreads and getThreadInfo methods to refer to their new versions. We assume that cannot be done in for this backport, because a super-interface cannot reference a sub-interface, and `com.sun.management.ThreadMXBean` is a sub-interface of `java.lang.management.ThreadMXBean`. This CSR does not include the references, since it does not change the java.lang.management.ThreadMXBean javadoc.

The original patch's javadoc uses @code to replace tt /tt pairs. The Java 8 javadoc uses the latter, so instances of @code have been replaced with the latter.

The original javadoc for the new getThreadInfo method included the line

     *    <li>the <a href="LockInfo.html#OwnableSynchronizer">

This does not work from com.sun.management.ThreadMXBean, so has been replaced by

     *    <li>the <a href="{@docRoot}/../api/java/lang/management/LockInfo.html#OwnableSynchronizer">


Summary
-------
Add two new methods, `com.sun.management.ThreadMXBean.dumpAllThreads` and `com.sun.management.ThreadMXBean.getThreadInfo`, with a `maxDepth` argument to limit the stack trace depth.

Problem
-------

Currently, `java.lang.management.ThreadMXBean.dumpAllThreads` and a version of `java.lang.management.ThreadMXBean.getThreadInfo` which includes `lockedMonitors` and `lockedSynchronizers` formal parameters, cannot limit returned stack trace depth as can another version of `java.lang.management.ThreadMXBean.getThreadInfo`. `java.lang.management.ThreadMXBean.dumpAllThreads` can therefore take excessive time/space for programs with thousands of threads.

Solution
--------

Add two new methods, `com.sun.management.ThreadMXBean.dumpAllThreads` and `com.sun.management.ThreadMXBean.getThreadInfo`, each with a `maxDepth` argument to limit the stack trace depth.


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

    /**                                                                                                                                                                                                                                                                                                                                                                     
     * Returns the thread info for each thread whose ID                                                                                                                                                                                                                                                                                                                     
     * is in the input array <tt>ids</tt>,                                                                                                                                                                                                                                                                                                                                  
     * with stack trace of the specified maximum number of elements                                                                                                                                                                                                                                                                                                         
     * and synchronization information.                                                                                                                                                                                                                                                                                                                                     
     * If <tt>maxDepth == 0</tt>, 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 <tt>lockedMonitors</tt> is <tt>true</tt>, and</li>                                                                                                                                                                                                                                                                                                         
     *    <li>the <a href="{@docRoot}/../api/java/lang/management/LockInfo.html#OwnableSynchronizer">                                                                                                                                                                                                                                                                       
     *        ownable synchronizers</a> currently locked by the thread                                                                                                                                                                                                                                                                                                      
     *        if <tt>lockedSynchronizers</tt> is <tt>true</tt>.</li>                                                                                                                                                                                                                                                                                                        
     * </ul>                                                                                                                                                                                                                                                                                                                                                                
     * <p>                                                                                                                                                                                                                                                                                                                                                                  
     * This method returns an array of the <tt>ThreadInfo</tt> objects,                                                                                                                                                                                                                                                                                                     
     * each is the thread information about the thread with the same index                                                                                                                                                                                                                                                                                                  
     * as in the <tt>ids</tt> array.                                                                                                                                                                                                                                                                                                                                        
     * If a thread of the given ID is not alive or does not exist,                                                                                                                                                                                                                                                                                                          
     * <tt>null</tt> 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 <tt>lockedMonitors</tt>                                                                                                                                                                                                                                                                                              
     * is <tt>false</tt>, the returned <tt>ThreadInfo</tt> object will have an                                                                                                                                                                                                                                                                                              
     * empty <tt>MonitorInfo</tt> array.  Similarly, if a thread does not                                                                                                                                                                                                                                                                                                   
     * lock any synchronizer or <tt>lockedSynchronizers</tt> is <tt>false</tt>,                                                                                                                                                                                                                                                                                             
     * the returned <tt>ThreadInfo</tt> object                                                                                                                                                                                                                                                                                                                              
     * will have an empty <tt>LockInfo</tt> array.                                                                                                                                                                                                                                                                                                                          
     *                                                                                                                                                                                                                                                                                                                                                                      
     * <p>                                                                                                                                                                                                                                                                                                                                                                  
     * When both <tt>lockedMonitors</tt> and <tt>lockedSynchronizers</tt>                                                                                                                                                                                                                                                                                                   
     * parameters are <tt>false</tt>, 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 <tt>ThreadInfo</tt> is                                                                                                                                                                                                                                                                                                                            
     * <tt>CompositeData</tt> with attributes as specified in the                                                                                                                                                                                                                                                                                                           
     * {@link ThreadInfo#from ThreadInfo.from} method.                                                                                                                                                                                                                                                                                                                      
     *                                                                                                                                                                                                                                                                                                                                                                      
     * @implSpec The default implementation throws                                                                                                                                                                                                                                                                                                                          
     * <tt>UnsupportedOperationException</tt>.                                                                                                                                                                                                                                                                                                                              
     *                                                                                                                                                                                                                                                                                                                                                                      
     * @param  ids an array of thread IDs.                                                                                                                                                                                                                                                                                                                                  
     * @param  lockedMonitors if <tt>true</tt>, retrieves all locked monitors.                                                                                                                                                                                                                                                                                              
     * @param  lockedSynchronizers if <tt>true</tt>, 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 <tt>maxDepth</tt> 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 <tt>lockedMonitors</tt> is <tt>true</tt> but                                                                                                                                                                                                                                                                                                        
     *               the Java virtual machine does not support monitoring                                                                                                                                                                                                                                                                                                   
     *               of {@linkplain #isObjectMonitorUsageSupported                                                                                                                                                                                                                                                                                                          
     *               object monitor usage}; or</li>                                                                                                                                                                                                                                                                                                                         
     *           <li>if <tt>lockedSynchronizers</tt> is <tt>true</tt> but                                                                                                                                                                                                                                                                                                   
     *               the Java virtual machine does not support monitoring                                                                                                                                                                                                                                                                                                   
     *               of {@linkplain #isSynchronizerUsageSupported                                                                                                                                                                                                                                                                                                           
     *               ownable synchronizer usage}.</li>                                                                                                                                                                                                                                                                                                                      
     *         </ul>                                                                                                                                                                                                                                                                                                                                                        
     *                                                                                                                                                                                                                                                                                                                                                                      
     * @see #isObjectMonitorUsageSupported                                                                                                                                                                                                                                                                                                                                  
     * @see #isSynchronizerUsageSupported                                                                                                                                                                                                                                                                                                                                   
     *                                                                                                                                                                                                                                                                                                                                                                      
     * @since 8u282                                                                                                                                                                                                                                                                                                                                                         
     */

    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 <tt>maxDepth == 0</tt>, 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                                                                                                                                                                                                                                                                                                                          
     * <tt>UnsupportedOperationException</tt>.                                                                                                                                                                                                                                                                                                                              
     *                                                                                                                                                                                                                                                                                                                                                                      
     * @param  lockedMonitors if <tt>true</tt>, dump all locked monitors.                                                                                                                                                                                                                                                                                                   
     * @param  lockedSynchronizers if <tt>true</tt>, 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 <tt>maxDepth</tt> 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 <tt>lockedMonitors</tt> is <tt>true</tt> but                                                                                                                                                                                                                                                                                                        
     *               the Java virtual machine does not support monitoring                                                                                                                                                                                                                                                                                                   
     *               of {@linkplain #isObjectMonitorUsageSupported                                                                                                                                                                                                                                                                                                          
     *               object monitor usage}; or</li>                                                                                                                                                                                                                                                                                                                         
     *           <li>if <tt>lockedSynchronizers</tt> is <tt>true</tt> but                                                                                                                                                                                                                                                                                                   
     *               the Java virtual machine does not support monitoring                                                                                                                                                                                                                                                                                                   
     *               of {@linkplain #isSynchronizerUsageSupported                                                                                                                                                                                                                                                                                                           
     *               ownable synchronizer usage}.</li>                                                                                                                                                                                                                                                                                                                      
     *         </ul>                                                                                                                                                                                                                                                                                                                                                        
     *                                                                                                                                                                                                                                                                                                                                                                      
     * @see #isObjectMonitorUsageSupported                                                                                                                                                                                                                                                                                                                                  
     * @see #isSynchronizerUsageSupported                                                                                                                                                                                                                                                                                                                                   
     *                                                                                                                                                                                                                                                                                                                                                                      
     * @since 8u282                                                                                                                                                                                                                                                                                                                                                         
     */
    public default ThreadInfo[] dumpAllThreads(boolean lockedMonitors,
                                               boolean lockedSynchronizers, int maxDepth) {
        throw new UnsupportedOperationException();
    }

    
 


Comments
Thank you, Joe. Completely understandable.
15-09-2020

Catching up after Skara, moving to Approved; sorry for the delay.
15-09-2020

I agree with Paul's comments on leaving JMM_VERSION untouched and still endorse the CSR.
01-09-2020

Updated CSR to reflect leaving JMM_VERSION along at 0x20010203 and targeting 8u282.
01-09-2020

Volker Simonis has pointed out in https://mail.openjdk.java.net/pipermail/jdk8u-dev/2020-August/012557.html that when we backport a JMM feature, we're actually updating the existing JMM version specification rather than transitioning to a new one. There was a bit of recognition of this in https://bugs.openjdk.java.net/browse/JDK-8249101, where the @since javadoc tag was updated to 11.0.9 rather than 14. Imo, Volker makes a good argument for leaving the JMM version alone when doing JMM backports. If we adopt this approach, the JDK 11 JMM version should also be reverted.
26-08-2020

Hi, Joe. Thanks for the clarification. Are there any gaps/changes you see/recommend?
25-08-2020

To provide more context, the CSR FAQ states: "Q: What sort of changes require CSR review? A: Any change to a JDK interface meant to be used outside of the JDK itself requires CSR review. ... Examples of interfaces by this definition include: - Changes to public and exported APIs in java.* and javax.* packages. - Changes to public and exported APIs in jdk.*packages. - ... " As the bulleted examples are clearly *not* meant to be exhaustive, since `com.sun.management.*` is "meant to be used outside of the JDK itself", this change is solidly within the the established and documented scope of the CSR. Since the CSR started reviewing JDK 10 changes and new uses items there were previously placed in `com.sun.*` should generally instead occur in `jdk.*` post-modules, it would deemed on net unhelpful to call out `com.sun.*` APIs explicitly.
24-08-2020

Thanks, Volker. Historically, any behavioral or API change to the JDK has required a CSR. E.g., JDK-8231209 and JDK-8231968 each required a CSR, even though the changes were only to com.sun.management.ThreadMXBean.
19-08-2020

I'm not even sure that this change strictly requires a CSR because the [CSR FAQs][1] mention that only "*Changes to public and exported APIs in `java.*`, `javax.*` and `jdk.*`*" packages require a CSR and these changes are intentionally in `com.sun.management.*`. Nevertheless, I consider these proposed extensions and their implementation as default methods safe and endorse them as a Reviewer. [1]: https://wiki.openjdk.java.net/display/csr/CSR+FAQs
19-08-2020