8185003: JMX: Add a version of ThreadMXBean.dumpAllThreads with a maxDepth argument
Summary: Added two new API's to limit the stack trace depth
Reviewed-by: mchung, dfuchs, rriggs, egahlin
Contributed-by: ujwal.vangapally@oracle.com
--- a/src/hotspot/share/services/jmm.h Wed Sep 20 18:30:32 2017 +0800
+++ b/src/hotspot/share/services/jmm.h Thu Oct 05 01:31:53 2017 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -50,7 +50,8 @@
JMM_VERSION_1_2 = 0x20010200, // JDK 7
JMM_VERSION_1_2_1 = 0x20010201, // JDK 7 GA
JMM_VERSION_1_2_2 = 0x20010202,
- JMM_VERSION = 0x20010203
+ JMM_VERSION_2 = 0x20020000, // JDK 10
+ JMM_VERSION = 0x20020000
};
typedef struct {
@@ -315,7 +316,8 @@
jobjectArray (JNICALL *DumpThreads) (JNIEnv *env,
jlongArray ids,
jboolean lockedMonitors,
- jboolean lockedSynchronizers);
+ jboolean lockedSynchronizers,
+ jint maxDepth);
void (JNICALL *SetGCNotificationEnabled) (JNIEnv *env,
jobject mgr,
jboolean enabled);
--- a/src/hotspot/share/services/management.cpp Wed Sep 20 18:30:32 2017 +0800
+++ b/src/hotspot/share/services/management.cpp Thu Oct 05 01:31:53 2017 -0700
@@ -1160,7 +1160,8 @@
// locked_monitors - if true, dump locked object monitors
// locked_synchronizers - if true, dump locked JSR-166 synchronizers
//
-JVM_ENTRY(jobjectArray, jmm_DumpThreads(JNIEnv *env, jlongArray thread_ids, jboolean locked_monitors, jboolean locked_synchronizers))
+JVM_ENTRY(jobjectArray, jmm_DumpThreads(JNIEnv *env, jlongArray thread_ids, jboolean locked_monitors,
+ jboolean locked_synchronizers, jint maxDepth))
ResourceMark rm(THREAD);
// make sure the AbstractOwnableSynchronizer klass is loaded before taking thread snapshots
@@ -1181,14 +1182,14 @@
do_thread_dump(&dump_result,
ids_ah,
num_threads,
- -1, /* entire stack */
+ maxDepth, /* stack depth */
(locked_monitors ? true : false), /* with locked monitors */
(locked_synchronizers ? true : false), /* with locked synchronizers */
CHECK_NULL);
} else {
// obtain thread dump of all threads
VM_ThreadDump op(&dump_result,
- -1, /* entire stack */
+ maxDepth, /* stack depth */
(locked_monitors ? true : false), /* with locked monitors */
(locked_synchronizers ? true : false) /* with locked synchronizers */);
VMThread::execute(&op);
@@ -2237,7 +2238,7 @@
void* Management::get_jmm_interface(int version) {
#if INCLUDE_MANAGEMENT
- if (version == JMM_VERSION_1_0) {
+ if (version == JMM_VERSION) {
return (void*) &jmm_interface;
}
#endif // INCLUDE_MANAGEMENT
--- a/src/hotspot/share/services/threadService.cpp Wed Sep 20 18:30:32 2017 +0800
+++ b/src/hotspot/share/services/threadService.cpp Thu Oct 05 01:31:53 2017 -0700
@@ -562,6 +562,10 @@
vframe* start_vf = _thread->last_java_vframe(®_map);
int count = 0;
for (vframe* f = start_vf; f; f = f->sender() ) {
+ if (maxDepth >= 0 && count == maxDepth) {
+ // Skip frames if more than maxDepth
+ break;
+ }
if (f->is_java_frame()) {
javaVFrame* jvf = javaVFrame::cast(f);
add_stack_frame(jvf);
@@ -569,10 +573,6 @@
} else {
// Ignore non-Java frames
}
- if (maxDepth > 0 && count == maxDepth) {
- // Skip frames if more than maxDepth
- break;
- }
}
}
--- a/src/java.management/share/classes/java/lang/management/ThreadMXBean.java Wed Sep 20 18:30:32 2017 +0800
+++ b/src/java.management/share/classes/java/lang/management/ThreadMXBean.java Thu Oct 05 01:31:53 2017 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -687,52 +687,13 @@
/**
* 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.
@@ -763,18 +724,110 @@
*
* @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 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
* 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
@@ -803,4 +856,56 @@
* @since 1.6
*/
public ThreadInfo[] dumpAllThreads(boolean lockedMonitors, boolean lockedSynchronizers);
+
+
+ /**
+ * 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();
+ }
}
--- a/src/java.management/share/classes/sun/management/ThreadImpl.java Wed Sep 20 18:30:32 2017 +0800
+++ b/src/java.management/share/classes/sun/management/ThreadImpl.java Thu Oct 05 01:31:53 2017 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -463,20 +463,43 @@
public ThreadInfo[] getThreadInfo(long[] ids,
boolean lockedMonitors,
boolean lockedSynchronizers) {
+ return dumpThreads0(ids, lockedMonitors, lockedSynchronizers,
+ Integer.MAX_VALUE);
+ }
+
+ public ThreadInfo[] getThreadInfo(long[] ids,
+ boolean lockedMonitors,
+ boolean lockedSynchronizers,
+ int maxDepth) {
+ if (maxDepth < 0) {
+ throw new IllegalArgumentException(
+ "Invalid maxDepth parameter: " + maxDepth);
+ }
verifyThreadIds(ids);
// ids has been verified to be non-null
// an empty array of ids should return an empty array of ThreadInfos
if (ids.length == 0) return new ThreadInfo[0];
verifyDumpThreads(lockedMonitors, lockedSynchronizers);
- return dumpThreads0(ids, lockedMonitors, lockedSynchronizers);
+ return dumpThreads0(ids, lockedMonitors, lockedSynchronizers, maxDepth);
}
@Override
public ThreadInfo[] dumpAllThreads(boolean lockedMonitors,
boolean lockedSynchronizers) {
+ return dumpAllThreads(lockedMonitors, lockedSynchronizers,
+ Integer.MAX_VALUE);
+ }
+
+ public ThreadInfo[] dumpAllThreads(boolean lockedMonitors,
+ boolean lockedSynchronizers,
+ int maxDepth) {
+ if (maxDepth < 0) {
+ throw new IllegalArgumentException(
+ "Invalid maxDepth parameter: " + maxDepth);
+ }
verifyDumpThreads(lockedMonitors, lockedSynchronizers);
- return dumpThreads0(null, lockedMonitors, lockedSynchronizers);
+ return dumpThreads0(null, lockedMonitors, lockedSynchronizers, maxDepth);
}
// VM support where maxDepth == -1 to request entire stack dump
@@ -497,7 +520,8 @@
private static native void resetPeakThreadCount0();
private static native ThreadInfo[] dumpThreads0(long[] ids,
boolean lockedMonitors,
- boolean lockedSynchronizers);
+ boolean lockedSynchronizers,
+ int maxDepth);
// tid == 0 to reset contention times for all threads
private static native void resetContentionTimes0(long tid);
--- a/src/java.management/share/native/include/jmm.h Wed Sep 20 18:30:32 2017 +0800
+++ b/src/java.management/share/native/include/jmm.h Thu Oct 05 01:31:53 2017 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -50,7 +50,8 @@
JMM_VERSION_1_2 = 0x20010200, // JDK 7
JMM_VERSION_1_2_1 = 0x20010201, // JDK 7 GA
JMM_VERSION_1_2_2 = 0x20010202,
- JMM_VERSION = 0x20010203
+ JMM_VERSION_2 = 0x20020000, // JDK 10
+ JMM_VERSION = 0x20020000
};
typedef struct {
@@ -315,7 +316,8 @@
jobjectArray (JNICALL *DumpThreads) (JNIEnv *env,
jlongArray ids,
jboolean lockedMonitors,
- jboolean lockedSynchronizers);
+ jboolean lockedSynchronizers,
+ jint maxDepth);
void (JNICALL *SetGCNotificationEnabled) (JNIEnv *env,
jobject mgr,
jboolean enabled);
--- a/src/java.management/share/native/libmanagement/ThreadImpl.c Wed Sep 20 18:30:32 2017 +0800
+++ b/src/java.management/share/native/libmanagement/ThreadImpl.c Thu Oct 05 01:31:53 2017 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -135,7 +135,9 @@
JNIEXPORT jobjectArray JNICALL
Java_sun_management_ThreadImpl_dumpThreads0
- (JNIEnv *env, jclass cls, jlongArray ids, jboolean lockedMonitors, jboolean lockedSynchronizers)
+ (JNIEnv *env, jclass cls, jlongArray ids, jboolean lockedMonitors,
+ jboolean lockedSynchronizers, jint maxDepth)
{
- return jmm_interface->DumpThreads(env, ids, lockedMonitors, lockedSynchronizers);
+ return jmm_interface->DumpThreads(env, ids, lockedMonitors,
+ lockedSynchronizers, maxDepth);
}
--- a/src/java.management/share/native/libmanagement/management.c Wed Sep 20 18:30:32 2017 +0800
+++ b/src/java.management/share/native/libmanagement/management.c Thu Oct 05 01:31:53 2017 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -44,7 +44,7 @@
return JNI_ERR;
}
- jmm_interface = (JmmInterface*) JVM_GetManagement(JMM_VERSION_1_0);
+ jmm_interface = (JmmInterface*) JVM_GetManagement(JMM_VERSION);
if (jmm_interface == NULL) {
JNU_ThrowInternalError(env, "Unsupported Management version");
return JNI_ERR;
--- a/src/jdk.management/share/native/libmanagement_ext/management_ext.c Wed Sep 20 18:30:32 2017 +0800
+++ b/src/jdk.management/share/native/libmanagement_ext/management_ext.c Thu Oct 05 01:31:53 2017 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -44,7 +44,7 @@
return JNI_ERR;
}
- jmm_interface = (JmmInterface*) JVM_GetManagement(JMM_VERSION_1_0);
+ jmm_interface = (JmmInterface*) JVM_GetManagement(JMM_VERSION);
if (jmm_interface == NULL) {
JNU_ThrowInternalError(env, "Unsupported Management version");
return JNI_ERR;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/management/ThreadMXBean/MaxDepthForThreadInfoTest.java Thu Oct 05 01:31:53 2017 -0700
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8185003
+ * @build ThreadDump
+ * @run main MaxDepthForThreadInfoTest
+ * @summary verifies the functionality of ThreadMXBean.dumpAllThreads
+ * and ThreadMXBean.getThreadInfo with maxDepth argument
+ */
+
+import java.lang.management.ManagementFactory;
+import java.lang.management.ThreadInfo;
+import java.lang.management.ThreadMXBean;
+
+
+
+public class MaxDepthForThreadInfoTest {
+
+
+ public static void main(String[] Args) {
+
+ ThreadMXBean tmxb = ManagementFactory.getThreadMXBean();
+
+ long[] threadIds = tmxb.getAllThreadIds();
+
+ ThreadInfo[] tinfos = tmxb.getThreadInfo(threadIds, true, true, 0);
+ for (ThreadInfo ti : tinfos) {
+ if (ti.getStackTrace().length > 0) {
+ ThreadDump.printThreadInfo(ti);
+ throw new RuntimeException("more than requested " +
+ "number of frames dumped");
+ }
+ }
+
+ tinfos = tmxb.getThreadInfo(threadIds, true, true, 3);
+ for (ThreadInfo ti : tinfos) {
+ if (ti.getStackTrace().length > 3) {
+ ThreadDump.printThreadInfo(ti);
+ throw new RuntimeException("more than requested " +
+ "number of frames dumped");
+ }
+ }
+
+ try {
+ tmxb.getThreadInfo(threadIds, true, true, -1);
+ throw new RuntimeException("Didn't throw IllegalArgumentException " +
+ "for negative maxdepth value");
+ } catch (IllegalArgumentException e) {
+ System.out.println("Throwed IllegalArgumentException as expected");
+ }
+
+ tinfos = tmxb.dumpAllThreads(true, true, 0);
+ for (ThreadInfo ti : tinfos) {
+ if (ti.getStackTrace().length > 0) {
+ ThreadDump.printThreadInfo(ti);
+ throw new RuntimeException("more than requested " +
+ "number of frames dumped");
+ }
+ }
+ tinfos = tmxb.dumpAllThreads(true, true, 2);
+ for (ThreadInfo ti : tinfos) {
+ if (ti.getStackTrace().length > 2) {
+ ThreadDump.printThreadInfo(ti);
+ throw new RuntimeException("more than requested " +
+ "number of frames dumped");
+ }
+ }
+
+ try {
+ tmxb.dumpAllThreads(true, true, -1);
+ throw new RuntimeException("Didn't throw IllegalArgumentException " +
+ "for negative maxdepth value");
+ } catch (IllegalArgumentException e) {
+ System.out.println("Throwed IllegalArgumentException as expected");
+ }
+
+ System.out.println("Test passed");
+ }
+}