# HG changeset patch # User jmanson # Date 1424767589 -3600 # Node ID 55f7a91aaa32c172868548313e4e4c4d1dedcf18 # Parent 56267f38f743f3aaf05d7f88c416ba289fd12198 6588467: Add isDaemon() and getPriority() to ThreadInfo Reviewed-by: mchung, sla, dholmes, martin diff -r 56267f38f743 -r 55f7a91aaa32 jdk/src/java.management/share/classes/java/lang/management/ThreadInfo.java --- a/jdk/src/java.management/share/classes/java/lang/management/ThreadInfo.java Mon Feb 23 11:40:48 2015 -0800 +++ b/jdk/src/java.management/share/classes/java/lang/management/ThreadInfo.java Tue Feb 24 09:46:29 2015 +0100 @@ -31,12 +31,13 @@ import static java.lang.Thread.State.*; /** - * Thread information. ThreadInfo contains the information + * Thread information. {@code ThreadInfo} contains the information * about a thread including: *
The Java virtual machine may measure the time with a high @@ -345,8 +361,8 @@ * the thread contention monitoring is reenabled. * * @return the approximate accumulated elapsed time in milliseconds - * that a thread entered the BLOCKED state; - * -1 if thread contention monitoring is disabled. + * that a thread entered the {@code BLOCKED} state; + * {@code -1} if thread contention monitoring is disabled. * * @throws java.lang.UnsupportedOperationException if the Java * virtual machine does not support this operation. @@ -360,13 +376,13 @@ /** * Returns the total number of times that - * the thread associated with this ThreadInfo + * the thread associated with this {@code ThreadInfo} * blocked to enter or reenter a monitor. * I.e. the number of times a thread has been in the * {@link java.lang.Thread.State#BLOCKED BLOCKED} state. * * @return the total number of times that the thread - * entered the BLOCKED state. + * entered the {@code BLOCKED} state. */ public long getBlockedCount() { return blockedCount; @@ -374,14 +390,14 @@ /** * Returns the approximate accumulated elapsed time (in milliseconds) - * that the thread associated with this ThreadInfo + * that the thread associated with this {@code ThreadInfo} * has waited for notification * since thread contention monitoring is enabled. * I.e. the total accumulated time the thread has been in the * {@link java.lang.Thread.State#WAITING WAITING} * or {@link java.lang.Thread.State#TIMED_WAITING TIMED_WAITING} state * since thread contention monitoring is enabled. - * This method returns -1 if thread contention monitoring + * This method returns {@code -1} if thread contention monitoring * is disabled. * *
The Java virtual machine may measure the time with a high @@ -389,9 +405,9 @@ * the thread contention monitoring is reenabled. * * @return the approximate accumulated elapsed time in milliseconds - * that a thread has been in the WAITING or - * TIMED_WAITING state; - * -1 if thread contention monitoring is disabled. + * that a thread has been in the {@code WAITING} or + * {@code TIMED_WAITING} state; + * {@code -1} if thread contention monitoring is disabled. * * @throws java.lang.UnsupportedOperationException if the Java * virtual machine does not support this operation. @@ -405,29 +421,29 @@ /** * Returns the total number of times that - * the thread associated with this ThreadInfo + * the thread associated with this {@code ThreadInfo} * waited for notification. * I.e. the number of times that a thread has been * in the {@link java.lang.Thread.State#WAITING WAITING} * or {@link java.lang.Thread.State#TIMED_WAITING TIMED_WAITING} state. * * @return the total number of times that the thread - * was in the WAITING or TIMED_WAITING state. + * was in the {@code WAITING} or {@code TIMED_WAITING} state. */ public long getWaitedCount() { return waitedCount; } /** - * Returns the LockInfo of an object for which - * the thread associated with this ThreadInfo + * Returns the {@code LockInfo} of an object for which + * the thread associated with this {@code ThreadInfo} * is blocked waiting. * A thread can be blocked waiting for one of the following: *
This method returns null if the thread is not in any of + *
This method returns {@code null} if the thread is not in any of * the above conditions. * - * @return LockInfo of an object for which the thread - * is blocked waiting if any; null otherwise. + * @return {@code LockInfo} of an object for which the thread + * is blocked waiting if any; {@code null} otherwise. * @since 1.6 */ public LockInfo getLockInfo() { @@ -462,19 +478,19 @@ /** * Returns the {@link LockInfo#toString string representation} * of an object for which the thread associated with this - * ThreadInfo is blocked waiting. + * {@code ThreadInfo} is blocked waiting. * This method is equivalent to calling: *
** - ** getLockInfo().toString() *
This method will return null if this thread is not blocked + *
This method will return {@code null} if this thread is not blocked * waiting for any object or if the object is not owned by any thread. * * @return the string representation of the object on which * the thread is blocked if any; - * null otherwise. + * {@code null} otherwise. * * @see #getLockInfo */ @@ -484,14 +500,14 @@ /** * Returns the ID of the thread which owns the object - * for which the thread associated with this ThreadInfo + * for which the thread associated with this {@code ThreadInfo} * is blocked waiting. - * This method will return -1 if this thread is not blocked + * This method will return {@code -1} if this thread is not blocked * waiting for any object or if the object is not owned by any thread. * * @return the thread ID of the owner thread of the object * this thread is blocked on; - * -1 if this thread is not blocked + * {@code -1} if this thread is not blocked * or if the object is not owned by any thread. * * @see #getLockInfo @@ -502,14 +518,14 @@ /** * Returns the name of the thread which owns the object - * for which the thread associated with this ThreadInfo + * for which the thread associated with this {@code ThreadInfo} * is blocked waiting. - * This method will return null if this thread is not blocked + * This method will return {@code null} if this thread is not blocked * waiting for any object or if the object is not owned by any thread. * * @return the name of the thread that owns the object * this thread is blocked on; - * null if this thread is not blocked + * {@code null} if this thread is not blocked * or if the object is not owned by any thread. * * @see #getLockInfo @@ -520,7 +536,7 @@ /** * Returns the stack trace of the thread - * associated with this ThreadInfo. + * associated with this {@code ThreadInfo}. * If no stack trace was requested for this thread info, this method * will return a zero-length array. * If the returned array is of non-zero length then the first element of @@ -532,42 +548,67 @@ *
Some Java virtual machines may, under some circumstances, omit one * or more stack frames from the stack trace. In the extreme case, * a virtual machine that has no stack trace information concerning - * the thread associated with this ThreadInfo + * the thread associated with this {@code ThreadInfo} * is permitted to return a zero-length array from this method. * - * @return an array of StackTraceElement objects of the thread. + * @return an array of {@code StackTraceElement} objects of the thread. */ public StackTraceElement[] getStackTrace() { return stackTrace; } /** - * Tests if the thread associated with this ThreadInfo - * is suspended. This method returns true if + * Tests if the thread associated with this {@code ThreadInfo} + * is suspended. This method returns {@code true} if * {@link Thread#suspend} has been called. * - * @return true if the thread is suspended; - * false otherwise. + * @return {@code true} if the thread is suspended; + * {@code false} otherwise. */ public boolean isSuspended() { return suspended; } /** - * Tests if the thread associated with this ThreadInfo + * Tests if the thread associated with this {@code ThreadInfo} * is executing native code via the Java Native Interface (JNI). * The JNI native code does not include * the virtual machine support code or the compiled native * code generated by the virtual machine. * - * @return true if the thread is executing native code; - * false otherwise. + * @return {@code true} if the thread is executing native code; + * {@code false} otherwise. */ public boolean isInNative() { return inNative; } /** + * Tests if the thread associated with this {@code ThreadInfo} is + * a {@linkplain Thread#isDaemon daemon thread}. + * + * @return {@code true} if the thread is a daemon thread, + * {@code false} otherwise. + * @see Thread#isDaemon + * @since 1.9 + */ + public boolean isDaemon() { + return daemon; + } + + /** + * Returns the {@linkplain Thread#getPriority() thread priority} of the + * thread associated with this {@code ThreadInfo}. + * + * @return The priority of the thread associated with this + * {@code ThreadInfo}. + * @since 1.9 + */ + public int getPriority() { + return priority; + } + + /** * Returns a string representation of this thread info. * The format of this string depends on the implementation. * The returned string will typically include @@ -580,6 +621,8 @@ */ public String toString() { StringBuilder sb = new StringBuilder("\"" + getThreadName() + "\"" + + (daemon ? " daemon" : "") + + " prio=" + priority + " Id=" + getThreadId() + " " + getThreadState()); if (getLockName() != null) { @@ -647,9 +690,9 @@ private static final int MAX_FRAMES = 8; /** - * Returns a ThreadInfo object represented by the - * given CompositeData. - * The given CompositeData must contain the following attributes + * Returns a {@code ThreadInfo} object represented by the + * given {@code CompositeData}. + * The given {@code CompositeData} must contain the following attributes * unless otherwise specified below: *
** - * @param cd CompositeData representing a ThreadInfo + * @param cd {@code CompositeData} representing a {@code ThreadInfo} * - * @throws IllegalArgumentException if cd does not - * represent a ThreadInfo with the attributes described + * @throws IllegalArgumentException if {@code cd} does not + * represent a {@code ThreadInfo} with the attributes described * above. * - * @return a ThreadInfo object represented - * by cd if cd is not null; - * null otherwise. + * @return a {@code ThreadInfo} object represented + * by {@code cd} if {@code cd} is not {@code null}; + * {@code null} otherwise. */ public static ThreadInfo from(CompositeData cd) { if (cd == null) { @@ -798,12 +849,12 @@ /** * Returns an array of {@link MonitorInfo} objects, each of which * represents an object monitor currently locked by the thread - * associated with this ThreadInfo. + * associated with this {@code ThreadInfo}. * If no locked monitor was requested for this thread info or * no monitor is locked by the thread, this method * will return a zero-length array. * - * @return an array of MonitorInfo objects representing + * @return an array of {@code MonitorInfo} objects representing * the object monitors locked by the thread. * * @since 1.6 @@ -816,11 +867,11 @@ * Returns an array of {@link LockInfo} objects, each of which * represents an ownable * synchronizer currently locked by the thread associated with - * this ThreadInfo. If no locked synchronizer was + * this {@code ThreadInfo}. If no locked synchronizer was * requested for this thread info or no synchronizer is locked by * the thread, this method will return a zero-length array. * - * @return an array of LockInfo objects representing + * @return an array of {@code LockInfo} objects representing * the ownable synchronizers locked by the thread. * * @since 1.6 diff -r 56267f38f743 -r 55f7a91aaa32 jdk/src/java.management/share/classes/sun/management/ThreadInfoCompositeData.java --- a/jdk/src/java.management/share/classes/sun/management/ThreadInfoCompositeData.java Mon Feb 23 11:40:48 2015 -0800 +++ b/jdk/src/java.management/share/classes/sun/management/ThreadInfoCompositeData.java Tue Feb 24 09:46:29 2015 +0100 @@ -43,23 +43,30 @@ private final ThreadInfo threadInfo; private final CompositeData cdata; private final boolean currentVersion; + private final boolean hasV6; private ThreadInfoCompositeData(ThreadInfo ti) { this.threadInfo = ti; this.currentVersion = true; this.cdata = null; + this.hasV6 = true; } private ThreadInfoCompositeData(CompositeData cd) { this.threadInfo = null; this.currentVersion = ThreadInfoCompositeData.isCurrentVersion(cd); this.cdata = cd; + this.hasV6 = ThreadInfoCompositeData.hasV6(cd); } public ThreadInfo getThreadInfo() { return threadInfo; } + public boolean hasV6() { + return hasV6; + } + public boolean isCurrentVersion() { return currentVersion; } @@ -124,6 +131,8 @@ threadInfo.isInNative(), lockedMonitorsData, lockedSyncsData, + threadInfo.isDaemon(), + threadInfo.getPriority(), }; try { @@ -151,6 +160,8 @@ private static final String STACK_TRACE = "stackTrace"; private static final String SUSPENDED = "suspended"; private static final String IN_NATIVE = "inNative"; + private static final String DAEMON = "daemon"; + private static final String PRIORITY = "priority"; private static final String LOCKED_MONITORS = "lockedMonitors"; private static final String LOCKED_SYNCS = "lockedSynchronizers"; @@ -171,6 +182,8 @@ IN_NATIVE, LOCKED_MONITORS, LOCKED_SYNCS, + DAEMON, + PRIORITY, }; // New attributes added in 6.0 ThreadInfo @@ -180,9 +193,16 @@ LOCKED_SYNCS, }; + private static final String[] threadInfoV9Attributes = { + DAEMON, + PRIORITY, + }; + // Current version of ThreadInfo private static final CompositeType threadInfoCompositeType; // Previous version of ThreadInfo + private static final CompositeType threadInfoV6CompositeType; + // Previous-previous version of ThreadInfo private static final CompositeType threadInfoV5CompositeType; private static final CompositeType lockInfoCompositeType; static { @@ -193,7 +213,7 @@ String[] itemNames = threadInfoCompositeType.keySet().toArray(new String[0]); int numV5Attributes = threadInfoItemNames.length - - threadInfoV6Attributes.length; + threadInfoV6Attributes.length - threadInfoV9Attributes.length; String[] v5ItemNames = new String[numV5Attributes]; String[] v5ItemDescs = new String[numV5Attributes]; OpenType>[] v5ItemTypes = new OpenType>[numV5Attributes]; @@ -213,6 +233,31 @@ v5ItemNames, v5ItemDescs, v5ItemTypes); + + + // Form a CompositeType for JDK 6.0 ThreadInfo version + int numV6Attributes = threadInfoItemNames.length - + threadInfoV9Attributes.length; + String[] v6ItemNames = new String[numV6Attributes]; + String[] v6ItemDescs = new String[numV6Attributes]; + OpenType>[] v6ItemTypes = new OpenType>[numV6Attributes]; + i = 0; + for (String n : itemNames) { + if (isV5Attribute(n) || isV6Attribute(n)) { + v6ItemNames[i] = n; + v6ItemDescs[i] = threadInfoCompositeType.getDescription(n); + v6ItemTypes[i] = threadInfoCompositeType.getType(n); + i++; + } + } + + threadInfoV6CompositeType = + new CompositeType("java.lang.management.ThreadInfo", + "Java SE 6 java.lang.management.ThreadInfo", + v6ItemNames, + v6ItemDescs, + v6ItemTypes); + } catch (OpenDataException e) { // Should never reach here throw new AssertionError(e); @@ -236,6 +281,20 @@ return false; } } + for (String n : threadInfoV9Attributes) { + if (itemName.equals(n)) { + return false; + } + } + return true; + } + + private static boolean isV6Attribute(String itemName) { + for (String n : threadInfoV9Attributes) { + if (itemName.equals(n)) { + return false; + } + } return true; } @@ -247,6 +306,15 @@ return isTypeMatched(threadInfoCompositeType, cd.getCompositeType()); } + private static boolean hasV6(CompositeData cd) { + if (cd == null) { + throw new NullPointerException("Null CompositeData"); + } + + return isTypeMatched(threadInfoCompositeType, cd.getCompositeType()) || + isTypeMatched(threadInfoV6CompositeType, cd.getCompositeType()); + } + public long threadId() { return getLong(cdata, THREAD_ID); } @@ -304,6 +372,14 @@ return getBoolean(cdata, IN_NATIVE); } + public boolean isDaemon() { + return getBoolean(cdata, DAEMON); + } + + public int getPriority(){ + return getInt(cdata, PRIORITY); + } + public StackTraceElement[] stackTrace() { CompositeData[] stackTraceData = (CompositeData[]) cdata.get(STACK_TRACE); @@ -368,9 +444,10 @@ if (!isTypeMatched(threadInfoCompositeType, type)) { currentVersion = false; // check if cd is an older version - if (!isTypeMatched(threadInfoV5CompositeType, type)) { - throw new IllegalArgumentException( - "Unexpected composite type for ThreadInfo"); + if (!isTypeMatched(threadInfoV5CompositeType, type) && + !isTypeMatched(threadInfoV6CompositeType, type)) { + throw new IllegalArgumentException( + "Unexpected composite type for ThreadInfo"); } } diff -r 56267f38f743 -r 55f7a91aaa32 jdk/test/java/lang/management/CompositeData/ThreadInfoCompositeData.java --- a/jdk/test/java/lang/management/CompositeData/ThreadInfoCompositeData.java Mon Feb 23 11:40:48 2015 -0800 +++ b/jdk/test/java/lang/management/CompositeData/ThreadInfoCompositeData.java Tue Feb 24 09:46:29 2015 +0100 @@ -147,6 +147,11 @@ info.getLockOwnerName() + " expected = " + values[LOCK_OWNER_NAME]); } + if (!values[DAEMON].equals(info.isDaemon())) { + throw new RuntimeException("Daemon = " + + info.isDaemon() + " expected = " + + values[DAEMON]); + } checkStackTrace(info.getStackTrace()); @@ -258,8 +263,11 @@ private static final int SUSPENDED = 11; private static final int IN_NATIVE = 12; private static final int NUM_V5_ATTS = 13; - // JDK 6.0 ThreadInfo attribtues + // JDK 6.0 ThreadInfo attributes private static final int LOCK_INFO = 13; + // JDK 9.0 ThreadInfo attributes + private static final int DAEMON = 14; + private static final int PRIORITY = 15; private static final String[] validItemNames = { "threadId", @@ -276,6 +284,8 @@ "suspended", "inNative", "lockInfo", + "daemon", + "priority", }; private static OpenType[] validItemTypes = { @@ -293,6 +303,8 @@ SimpleType.BOOLEAN, SimpleType.BOOLEAN, null, // CompositeType for LockInfo + SimpleType.BOOLEAN, + SimpleType.INTEGER, }; private static Object[] values = { @@ -310,6 +322,8 @@ new Boolean(false), new Boolean(false), null, // To be initialized to lockInfoCD + new Boolean(false), + Thread.NORM_PRIORITY, }; private static final String[] steItemNames = { @@ -381,6 +395,8 @@ "suspended", "inNative", "lockInfo", + "daemon", + "priority", }; private static final OpenType[] badItemTypes = { SimpleType.LONG, @@ -397,6 +413,8 @@ SimpleType.BOOLEAN, SimpleType.BOOLEAN, SimpleType.LONG, // bad type + SimpleType.BOOLEAN, + SimpleType.INTEGER, }; } diff -r 56267f38f743 -r 55f7a91aaa32 jdk/test/java/lang/management/ThreadMXBean/ThreadDaemonTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/lang/management/ThreadMXBean/ThreadDaemonTest.java Tue Feb 24 09:46:29 2015 +0100 @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2015, 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. + */ + +import java.lang.management.*; +import java.util.*; +import java.util.concurrent.*; +import java.util.concurrent.atomic.*; + +/* + * @test + * @bug 6588467 + * @summary Basic test of ThreadInfo.isDaemon + * @author Jeremy Manson + */ +public class ThreadDaemonTest { + + public static void main(String[] args) throws Exception { + final int NUM_THREADS = 20; + final String THREAD_PREFIX = "ThreadDaemonTest-"; + + final CountDownLatch started = new CountDownLatch(NUM_THREADS); + final CountDownLatch finished = new CountDownLatch(1); + final AtomicReference@@ -659,67 +702,67 @@ * *
** *threadId - *java.lang.Long + *{@code java.lang.Long} ** *threadName - *java.lang.String + *{@code java.lang.String} ** *threadState - *java.lang.String + *{@code java.lang.String} ** *suspended - *java.lang.Boolean + *{@code java.lang.Boolean} ** *inNative - *java.lang.Boolean + *{@code java.lang.Boolean} ** *blockedCount - *java.lang.Long + *{@code java.lang.Long} ** *blockedTime - *java.lang.Long + *{@code java.lang.Long} ** *waitedCount - *java.lang.Long + *{@code java.lang.Long} ** *waitedTime - *java.lang.Long + *{@code java.lang.Long} ** *lockInfo - *javax.management.openmbean.CompositeData + * {@code javax.management.openmbean.CompositeData} * - the mapped type for {@link LockInfo} as specified in the * {@link LockInfo#from} method. * + * If {@code cd} does not contain this attribute, + * the {@code LockInfo} object will be constructed from + * the value of the {@code lockName} attribute. *- * If cd does not contain this attribute, - * the LockInfo object will be constructed from - * the value of the lockName attribute.
* *lockName - *java.lang.String + *{@code java.lang.String} ** *lockOwnerId - *java.lang.Long + *{@code java.lang.Long} ** *lockOwnerName - *java.lang.String + *{@code java.lang.String} ** *stackTrace - *javax.management.openmbean.CompositeData[] + * {@code javax.management.openmbean.CompositeData[]} * - * Each element is a CompositeData representing + * Each element is a {@code CompositeData} representing * StackTraceElement containing the following attributes: *
*@@ -753,35 +796,43 @@ *@@ -729,23 +772,23 @@ * *
** *className - *java.lang.String + *{@code java.lang.String} ** *methodName - *java.lang.String + *{@code java.lang.String} ** *fileName - *java.lang.String + *{@code java.lang.String} ** *lineNumber - *java.lang.Integer + *{@code java.lang.Integer} ** *nativeMethod - *java.lang.Boolean + *{@code java.lang.Boolean} ** *lockedMonitors - *javax.management.openmbean.CompositeData[] + * {@code javax.management.openmbean.CompositeData[]} * whose element type is the mapped type for * {@link MonitorInfo} as specified in the * {@link MonitorInfo#from Monitor.from} method. * *- * If cd does not contain this attribute, + * If {@code cd} does not contain this attribute, * this attribute will be set to an empty array.
* + *lockedSynchronizers - *javax.management.openmbean.CompositeData[] + * {@code javax.management.openmbean.CompositeData[]} * whose element type is the mapped type for * {@link LockInfo} as specified in the {@link LockInfo#from} method. * *- * If cd does not contain this attribute, + * If {@code cd} does not contain this attribute, * this attribute will be set to an empty array.
+ * + *daemon + *{@code java.lang.Boolean} + *+ * *priority + *{@code java.lang.Integer} + *