6173675: M&M: approximate memory allocation rate/amount per thread
authorphh
Thu, 20 Jan 2011 19:34:40 -0500
changeset 8001 192adf3627b7
parent 7993 8778b8786a81
child 8002 5d022b92fbef
6173675: M&M: approximate memory allocation rate/amount per thread Summary: Subclass com.sun.management.ThreadMXBean from java.lang.management.ThreadMXBean, add getAllocatedBytes() and friends to c.s.m.ThreadMXBean and have sun.management.ThreadImpl implement c.s.m.ThreadMXBean rather than j.l.m.ThreadMXBean. Reviewed-by: mchung, alanb, dholmes, emcmanus
jdk/make/java/management/mapfile-vers
jdk/src/share/classes/com/sun/management/ThreadMXBean.java
jdk/src/share/classes/sun/management/ThreadImpl.java
jdk/src/share/classes/sun/management/VMManagement.java
jdk/src/share/classes/sun/management/VMManagementImpl.java
jdk/src/share/javavm/export/jmm.h
jdk/src/share/native/sun/management/ThreadImpl.c
jdk/src/share/native/sun/management/VMManagementImpl.c
jdk/test/com/sun/management/ThreadMXBean/ThreadAllocatedMemory.java
jdk/test/com/sun/management/ThreadMXBean/ThreadAllocatedMemoryArray.java
jdk/test/com/sun/management/ThreadMXBean/ThreadCpuTimeArray.java
--- a/jdk/make/java/management/mapfile-vers	Thu Jan 20 15:23:57 2011 +0000
+++ b/jdk/make/java/management/mapfile-vers	Thu Jan 20 19:34:40 2011 -0500
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2005, 2011, 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
@@ -70,14 +70,18 @@
 	    Java_sun_management_ThreadImpl_dumpThreads0;
 	    Java_sun_management_ThreadImpl_findDeadlockedThreads0;
 	    Java_sun_management_ThreadImpl_findMonitorDeadlockedThreads0;
-	    Java_sun_management_ThreadImpl_getThreadInfo0;
+	    Java_sun_management_ThreadImpl_getThreadInfo1;
 	    Java_sun_management_ThreadImpl_getThreads;
 	    Java_sun_management_ThreadImpl_getThreadTotalCpuTime0;
+	    Java_sun_management_ThreadImpl_getThreadTotalCpuTime1;
 	    Java_sun_management_ThreadImpl_getThreadUserCpuTime0;
+	    Java_sun_management_ThreadImpl_getThreadUserCpuTime1;
+	    Java_sun_management_ThreadImpl_getThreadAllocatedMemory1;
 	    Java_sun_management_ThreadImpl_resetContentionTimes0;
 	    Java_sun_management_ThreadImpl_resetPeakThreadCount0;
 	    Java_sun_management_ThreadImpl_setThreadContentionMonitoringEnabled0;
 	    Java_sun_management_ThreadImpl_setThreadCpuTimeEnabled0;
+	    Java_sun_management_ThreadImpl_setThreadAllocatedMemoryEnabled0;
 	    Java_sun_management_VMManagementImpl_getAvailableProcessors;
 	    Java_sun_management_VMManagementImpl_getClassInitializationTime;
 	    Java_sun_management_VMManagementImpl_getClassLoadingTime;
@@ -106,6 +110,7 @@
 	    Java_sun_management_VMManagementImpl_initOptionalSupportFields;
 	    Java_sun_management_VMManagementImpl_isThreadContentionMonitoringEnabled;
 	    Java_sun_management_VMManagementImpl_isThreadCpuTimeEnabled;
+	    Java_sun_management_VMManagementImpl_isThreadAllocatedMemoryEnabled;
             JNI_OnLoad;
 	local:
 	    *;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/com/sun/management/ThreadMXBean.java	Thu Jan 20 19:34:40 2011 -0500
@@ -0,0 +1,221 @@
+/*
+ * Copyright (c) 2011, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+package com.sun.management;
+
+import java.util.Map;
+
+/**
+ * Platform-specific management interface for the thread system
+ * of the Java virtual machine.
+ * <p>
+ * This platform extension is only available to a thread
+ * implementation that supports this extension.
+ *
+ * @author  Paul Hohensee
+ * @since   6u25
+ */
+
+public interface ThreadMXBean extends java.lang.management.ThreadMXBean {
+    /**
+     * Returns the total CPU time for each thread whose ID is
+     * in the input array {@code ids} in nanoseconds.
+     * The returned values are of nanoseconds precision but
+     * not necessarily nanoseconds accuracy.
+     * <p>
+     * This method is equivalent to calling the
+     * {@link ThreadMXBean#getThreadCpuTime(long)}
+     * method for each thread ID in the input array {@code ids} and setting the
+     * returned value in the corresponding element of the returned array.
+     *
+     * @param ids an array of thread IDs.
+     * @return an array of long values, each of which is the amount of CPU
+     * time the thread whose ID is in the corresponding element of the input
+     * array of IDs has used,
+     * if the thread of a specified ID exists, the thread is alive,
+     * and CPU time measurement is enabled;
+     * {@code -1} otherwise.
+     *
+     * @throws NullPointerException if {@code ids} is {@code null}
+     * @throws IllegalArgumentException if any element in the input array
+     *         {@code ids} is {@code <=} {@code 0}.
+     * @throws java.lang.UnsupportedOperationException if the Java
+     *         virtual machine implementation does not support CPU time
+     *         measurement.
+     *
+     * @see ThreadMXBean#getThreadCpuTime(long)
+     * @see #getThreadUserTime
+     * @see ThreadMXBean#isThreadCpuTimeSupported
+     * @see ThreadMXBean#isThreadCpuTimeEnabled
+     * @see ThreadMXBean#setThreadCpuTimeEnabled
+     */
+    public long[] getThreadCpuTime(long[] ids);
+
+    /**
+     * Returns the CPU time that each thread whose ID is in the input array
+     * {@code ids} has executed in user mode in nanoseconds.
+     * The returned values are of nanoseconds precision but
+     * not necessarily nanoseconds accuracy.
+     * <p>
+     * This method is equivalent to calling the
+     * {@link ThreadMXBean#getThreadUserTime(long)}
+     * method for each thread ID in the input array {@code ids} and setting the
+     * returned value in the corresponding element of the returned array.
+     *
+     * @param ids an array of thread IDs.
+     * @return an array of long values, each of which is the amount of user
+     * mode CPU time the thread whose ID is in the corresponding element of
+     * the input array of IDs has used,
+     * if the thread of a specified ID exists, the thread is alive,
+     * and CPU time measurement is enabled;
+     * {@code -1} otherwise.
+     *
+     * @throws NullPointerException if {@code ids} is {@code null}
+     * @throws IllegalArgumentException if any element in the input array
+     *         {@code ids} is {@code <=} {@code 0}.
+     * @throws java.lang.UnsupportedOperationException if the Java
+     *         virtual machine implementation does not support CPU time
+     *         measurement.
+     *
+     * @see ThreadMXBean#getThreadUserTime(long)
+     * @see #getThreadCpuTime
+     * @see ThreadMXBean#isThreadCpuTimeSupported
+     * @see ThreadMXBean#isThreadCpuTimeEnabled
+     * @see ThreadMXBean#setThreadCpuTimeEnabled
+     */
+    public long[] getThreadUserTime(long[] ids);
+
+    /**
+     * Returns an approximation of the total amount of memory, in bytes,
+     * allocated in heap memory for the thread of the specified ID.
+     * The returned value is an approximation because some Java virtual machine
+     * implementations may use object allocation mechanisms that result in a
+     * delay between the time an object is allocated and the time its size is
+     * recorded.
+     * <p>
+     * If the thread of the specified ID is not alive or does not exist,
+     * this method returns {@code -1}. If thread memory allocation measurement
+     * is disabled, this method returns {@code -1}.
+     * A thread is alive if it has been started and has not yet died.
+     * <p>
+     * If thread memory allocation measurement is enabled after the thread has
+     * started, the Java virtual machine implementation may choose any time up
+     * to and including the time that the capability is enabled as the point
+     * where thread memory allocation measurement starts.
+     *
+     * @param id the thread ID of a thread
+     * @return an approximation of the total memory allocated, in bytes, in
+     * heap memory for a thread of the specified ID
+     * if the thread of the specified ID exists, the thread is alive,
+     * and thread memory allocation measurement is enabled;
+     * {@code -1} otherwise.
+     *
+     * @throws IllegalArgumentException if {@code id} {@code <=} {@code 0}.
+     * @throws java.lang.UnsupportedOperationException if the Java virtual
+     *         machine implementation does not support thread memory allocation
+     *         measurement.
+     *
+     * @see #isThreadAllocatedMemorySupported
+     * @see #isThreadAllocatedMemoryEnabled
+     * @see #setThreadAllocatedMemoryEnabled
+     */
+    public long getThreadAllocatedBytes(long id);
+
+    /**
+     * Returns an approximation of the total amount of memory, in bytes,
+     * allocated in heap memory for each thread whose ID is in the input
+     * array {@code ids}.
+     * The returned values are approximations because some Java virtual machine
+     * implementations may use object allocation mechanisms that result in a
+     * delay between the time an object is allocated and the time its size is
+     * recorded.
+     * <p>
+     * This method is equivalent to calling the
+     * {@link #getThreadAllocatedBytes(long)}
+     * method for each thread ID in the input array {@code ids} and setting the
+     * returned value in the corresponding element of the returned array.
+     *
+     * @param ids an array of thread IDs.
+     * @return an array of long values, each of which is an approximation of
+     * the total memory allocated, in bytes, in heap memory for the thread
+     * whose ID is in the corresponding element of the input array of IDs.
+     *
+     * @throws NullPointerException if {@code ids} is {@code null}
+     * @throws IllegalArgumentException if any element in the input array
+     *         {@code ids} is {@code <=} {@code 0}.
+     * @throws java.lang.UnsupportedOperationException if the Java virtual
+     *         machine implementation does not support thread memory allocation
+     *         measurement.
+     *
+     * @see #getThreadAllocatedBytes(long)
+     * @see #isThreadAllocatedMemorySupported
+     * @see #isThreadAllocatedMemoryEnabled
+     * @see #setThreadAllocatedMemoryEnabled
+     */
+    public long[] getThreadAllocatedBytes(long[] ids);
+
+    /**
+     * Tests if the Java virtual machine implementation supports thread memory
+     * allocation measurement.
+     *
+     * @return
+     *   {@code true}
+     *     if the Java virtual machine implementation supports thread memory
+     *     allocation measurement;
+     *   {@code false} otherwise.
+     */
+    public boolean isThreadAllocatedMemorySupported();
+
+    /**
+     * Tests if thread memory allocation measurement is enabled.
+     *
+     * @return {@code true} if thread memory allocation measurement is enabled;
+     *         {@code false} otherwise.
+     *
+     * @throws java.lang.UnsupportedOperationException if the Java virtual
+     *         machine does not support thread memory allocation measurement.
+     *
+     * @see #isThreadAllocatedMemorySupported
+     */
+    public boolean isThreadAllocatedMemoryEnabled();
+
+    /**
+     * Enables or disables thread memory allocation measurement.  The default
+     * is platform dependent.
+     *
+     * @param enable {@code true} to enable;
+     *               {@code false} to disable.
+     *
+     * @throws java.lang.UnsupportedOperationException if the Java virtual
+     *         machine does not support thread memory allocation measurement.
+     *
+     * @throws java.lang.SecurityException if a security manager
+     *         exists and the caller does not have
+     *         ManagementPermission("control").
+     *
+     * @see #isThreadAllocatedMemorySupported
+     */
+    public void setThreadAllocatedMemoryEnabled(boolean enable);
+}
--- a/jdk/src/share/classes/sun/management/ThreadImpl.java	Thu Jan 20 15:23:57 2011 +0000
+++ b/jdk/src/share/classes/sun/management/ThreadImpl.java	Thu Jan 20 19:34:40 2011 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2011, 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
@@ -25,7 +25,6 @@
 
 package sun.management;
 
-import java.lang.management.ThreadMXBean;
 import java.lang.management.ManagementFactory;
 
 import java.lang.management.ThreadInfo;
@@ -39,13 +38,14 @@
  * ManagementFactory.getThreadMXBean() returns an instance
  * of this class.
  */
-class ThreadImpl implements ThreadMXBean {
+class ThreadImpl implements com.sun.management.ThreadMXBean {
 
     private final VMManagement jvm;
 
     // default for thread contention monitoring is disabled.
     private boolean contentionMonitoringEnabled = false;
     private boolean cpuTimeEnabled;
+    private boolean allocatedMemoryEnabled;
 
     /**
      * Constructor of ThreadImpl class.
@@ -53,6 +53,7 @@
     ThreadImpl(VMManagement vm) {
         this.jvm = vm;
         this.cpuTimeEnabled = jvm.isThreadCpuTimeEnabled();
+        this.allocatedMemoryEnabled = jvm.isThreadAllocatedMemoryEnabled();
     }
 
     public int getThreadCount() {
@@ -91,6 +92,10 @@
         return jvm.isCurrentThreadCpuTimeSupported();
     }
 
+    public boolean isThreadAllocatedMemorySupported() {
+        return jvm.isThreadAllocatedMemorySupported();
+    }
+
     public boolean isThreadCpuTimeEnabled() {
         if (!isThreadCpuTimeSupported() &&
             !isCurrentThreadCpuTimeSupported()) {
@@ -100,6 +105,14 @@
         return cpuTimeEnabled;
     }
 
+    public boolean isThreadAllocatedMemoryEnabled() {
+        if (!isThreadAllocatedMemorySupported()) {
+            throw new UnsupportedOperationException(
+                "Thread allocated memory measurement is not supported");
+        }
+        return allocatedMemoryEnabled;
+    }
+
     public long[] getAllThreadIds() {
         Util.checkMonitorAccess();
 
@@ -114,11 +127,6 @@
     }
 
     public ThreadInfo getThreadInfo(long id) {
-        if (id <= 0) {
-            throw new IllegalArgumentException(
-                "Invalid thread ID parameter: " + id);
-        }
-
         long[] ids = new long[1];
         ids[0] = id;
         final ThreadInfo[] infos = getThreadInfo(ids, 0);
@@ -126,15 +134,6 @@
     }
 
     public ThreadInfo getThreadInfo(long id, int maxDepth) {
-        if (id <= 0) {
-            throw new IllegalArgumentException(
-                "Invalid thread ID parameter: " + id);
-        }
-        if (maxDepth < 0) {
-            throw new IllegalArgumentException(
-                "Invalid maxDepth parameter: " + maxDepth);
-        }
-
         long[] ids = new long[1];
         ids[0] = id;
         final ThreadInfo[] infos = getThreadInfo(ids, maxDepth);
@@ -145,11 +144,22 @@
         return getThreadInfo(ids, 0);
     }
 
-    public ThreadInfo[] getThreadInfo(long[] ids, int maxDepth) {
+    private void verifyThreadIds(long[] ids) {
         if (ids == null) {
             throw new NullPointerException("Null ids parameter.");
         }
 
+        for (int i = 0; i < ids.length; i++) {
+            if (ids[i] <= 0) {
+                throw new IllegalArgumentException(
+                    "Invalid thread ID parameter: " + ids[i]);
+            }
+        }
+    }
+
+    public ThreadInfo[] getThreadInfo(long[] ids, int maxDepth) {
+        verifyThreadIds(ids);
+
         if (maxDepth < 0) {
             throw new IllegalArgumentException(
                 "Invalid maxDepth parameter: " + maxDepth);
@@ -157,17 +167,15 @@
 
         Util.checkMonitorAccess();
 
-        ThreadInfo[] infos = new ThreadInfo[ids.length];
+        ThreadInfo[] infos = new ThreadInfo[ids.length]; // nulls
         if (maxDepth == Integer.MAX_VALUE) {
-            getThreadInfo0(ids, -1, infos);
+            getThreadInfo1(ids, -1, infos);
         } else {
-            getThreadInfo0(ids, maxDepth, infos);
+            getThreadInfo1(ids, maxDepth, infos);
         }
         return infos;
     }
 
-
-
     public void setThreadContentionMonitoringEnabled(boolean enable) {
         if (!isThreadContentionMonitoringSupported()) {
             throw new UnsupportedOperationException(
@@ -192,69 +200,32 @@
         }
     }
 
-    public long getCurrentThreadCpuTime() {
+    private boolean verifyCurrentThreadCpuTime() {
         // check if Thread CPU time measurement is supported.
         if (!isCurrentThreadCpuTimeSupported()) {
             throw new UnsupportedOperationException(
                 "Current thread CPU time measurement is not supported.");
         }
+        return isThreadCpuTimeEnabled();
+    }
 
-        if (!isThreadCpuTimeEnabled()) {
-            return -1;
+    public long getCurrentThreadCpuTime() {
+        if (verifyCurrentThreadCpuTime()) {
+            return getThreadTotalCpuTime0(0);
         }
-
-        return getThreadTotalCpuTime0(0);
+        return -1;
     }
 
     public long getThreadCpuTime(long id) {
-        // check if Thread CPU time measurement is supported.
-        if (!isThreadCpuTimeSupported() &&
-            !isCurrentThreadCpuTimeSupported()) {
-            throw new UnsupportedOperationException(
-                "Thread CPU Time Measurement is not supported.");
-        }
-
-        if (!isThreadCpuTimeSupported()) {
-            // support current thread only
-            if (id != Thread.currentThread().getId()) {
-                throw new UnsupportedOperationException(
-                    "Thread CPU Time Measurement is only supported" +
-                    " for the current thread.");
-            }
-        }
-
-        if (id <= 0) {
-            throw new IllegalArgumentException(
-                "Invalid thread ID parameter: " + id);
-        }
-
-        if (!isThreadCpuTimeEnabled()) {
-            return -1;
-        }
-
-        if (id == Thread.currentThread().getId()) {
-            // current thread
-            return getThreadTotalCpuTime0(0);
-        } else {
-            return getThreadTotalCpuTime0(id);
-        }
+        long[] ids = new long[1];
+        ids[0] = id;
+        final long[] times = getThreadCpuTime(ids);
+        return times[0];
     }
 
-    public long getCurrentThreadUserTime() {
-        // check if Thread CPU time measurement is supported.
-        if (!isCurrentThreadCpuTimeSupported()) {
-            throw new UnsupportedOperationException(
-                "Current thread CPU time measurement is not supported.");
-        }
+    private boolean verifyThreadCpuTime(long[] ids) {
+        verifyThreadIds(ids);
 
-        if (!isThreadCpuTimeEnabled()) {
-            return -1;
-        }
-
-        return getThreadUserCpuTime0(0);
-    }
-
-    public long getThreadUserTime(long id) {
         // check if Thread CPU time measurement is supported.
         if (!isThreadCpuTimeSupported() &&
             !isCurrentThreadCpuTimeSupported()) {
@@ -264,30 +235,71 @@
 
         if (!isThreadCpuTimeSupported()) {
             // support current thread only
-            if (id != Thread.currentThread().getId()) {
-                throw new UnsupportedOperationException(
-                    "Thread CPU time measurement is only supported" +
-                    " for the current thread.");
+            for (int i = 0; i < ids.length; i++) {
+                if (ids[i] != Thread.currentThread().getId()) {
+                    throw new UnsupportedOperationException(
+                        "Thread CPU time measurement is only supported" +
+                        " for the current thread.");
+                }
             }
         }
 
-        if (id <= 0) {
-            throw new IllegalArgumentException(
-                "Invalid thread ID parameter: " + id);
-        }
+        return isThreadCpuTimeEnabled();
+    }
+
+    public long[] getThreadCpuTime(long[] ids) {
+        boolean verified = verifyThreadCpuTime(ids);
+
+        int length = ids.length;
+        long[] times = java.util.Arrays.fill(new long[length], -1);
 
-        if (!isThreadCpuTimeEnabled()) {
-            return -1;
+        if (verified) {
+            if (length == 1) {
+                long id = ids[0];
+                if (id == Thread.currentThread().getId()) {
+                    id = 0;
+                }
+                getThreadTotalCpuTime0(id);
+            } else {
+                getThreadTotalCpuTime1(ids, times);
+            }
         }
-
-        if (id == Thread.currentThread().getId()) {
-            // current thread
-           return getThreadUserCpuTime0(0);
-        } else {
-           return getThreadUserCpuTime0(id);
-        }
+        return times;
     }
 
+    public long getCurrentThreadUserTime() {
+        if (verifyCurrentThreadCpuTime()) {
+            return getThreadUserCpuTime0(0);
+        }
+        return -1;
+    }
+
+    public long getThreadUserTime(long id) {
+        long[] ids = new long[1];
+        ids[0] = id;
+        final long[] times = getThreadUserTime(ids);
+        return times[0];
+    }
+
+    public long[] getThreadUserTime(long[] ids) {
+        boolean verified = verifyThreadCpuTime(ids);
+
+        int length = ids.length;
+        long[] times = java.util.Arrays.fill(new long[length], -1);
+
+        if (verified) {
+            if (length == 1) {
+                long id = ids[0];
+                if (id == Thread.currentThread().getId()) {
+                    id = 0;
+                }
+                times[0] = getThreadUserCpuTime0(id);
+            } else {
+                getThreadUserCpuTime1(ids, times);
+            }
+        }
+        return times;
+    }
 
     public void setThreadCpuTimeEnabled(boolean enable) {
         if (!isThreadCpuTimeSupported() &&
@@ -299,13 +311,59 @@
         Util.checkControlAccess();
         synchronized (this) {
             if (cpuTimeEnabled != enable) {
-                // update VM of the state change
+                // notify VM of the state change
                 setThreadCpuTimeEnabled0(enable);
                 cpuTimeEnabled = enable;
             }
         }
     }
 
+    public long getThreadAllocatedBytes(long id) {
+        long[] ids = new long[1];
+        ids[0] = id;
+        final long[] sizes = getThreadAllocatedBytes(ids);
+        return sizes[0];
+    }
+
+    private boolean verifyThreadAllocatedMemory(long[] ids) {
+        verifyThreadIds(ids);
+
+        // check if Thread allocated memory measurement is supported.
+        if (!isThreadAllocatedMemorySupported()) {
+            throw new UnsupportedOperationException(
+                "Thread allocated memory measurement is not supported.");
+        }
+
+        return isThreadAllocatedMemoryEnabled();
+    }
+
+    public long[] getThreadAllocatedBytes(long[] ids) {
+        boolean verified = verifyThreadAllocatedMemory(ids);
+
+        long[] times = java.util.Arrays.fill(new long[length], -1);
+
+        if (verified) {
+            getThreadAllocatedMemory1(ids, sizes);
+        }
+        return sizes;
+    }
+
+    public void setThreadAllocatedMemoryEnabled(boolean enable) {
+        if (!isThreadAllocatedMemorySupported()) {
+            throw new UnsupportedOperationException(
+                "Thread allocated memory measurement is not supported.");
+        }
+
+        Util.checkControlAccess();
+        synchronized (this) {
+            if (allocatedMemoryEnabled != enable) {
+                // notify VM of the state change
+                setThreadAllocatedMemoryEnabled0(enable);
+                allocatedMemoryEnabled = enable;
+            }
+        }
+    }
+
     public long[] findMonitorDeadlockedThreads() {
         Util.checkMonitorAccess();
 
@@ -356,49 +414,47 @@
         return jvm.isSynchronizerUsageSupported();
     }
 
-    public ThreadInfo[] getThreadInfo(long[] ids,
-                                      boolean lockedMonitors,
-                                      boolean lockedSynchronizers) {
-        if (ids == null) {
-            throw new NullPointerException("Null ids parameter.");
-        }
-
+    private void verifyDumpThreads(boolean lockedMonitors,
+                                   boolean lockedSynchronizers) {
         if (lockedMonitors && !isObjectMonitorUsageSupported()) {
             throw new UnsupportedOperationException(
                 "Monitoring of Object Monitor Usage is not supported.");
         }
+
         if (lockedSynchronizers && !isSynchronizerUsageSupported()) {
             throw new UnsupportedOperationException(
                 "Monitoring of Synchronizer Usage is not supported.");
         }
 
         Util.checkMonitorAccess();
+    }
+
+    public ThreadInfo[] getThreadInfo(long[] ids,
+                                      boolean lockedMonitors,
+                                      boolean lockedSynchronizers) {
+        verifyThreadIds(ids);
+        verifyDumpThreads(lockedMonitors, lockedSynchronizers);
         return dumpThreads0(ids, lockedMonitors, lockedSynchronizers);
     }
 
-
-    public ThreadInfo[] dumpAllThreads(boolean lockedMonitors, boolean lockedSynchronizers) {
-        if (lockedMonitors && !isObjectMonitorUsageSupported()) {
-            throw new UnsupportedOperationException(
-                "Monitoring of Object Monitor Usage is not supported.");
-        }
-        if (lockedSynchronizers && !isSynchronizerUsageSupported()) {
-            throw new UnsupportedOperationException(
-                "Monitoring of Synchronizer Usage is not supported.");
-        }
-
-        Util.checkMonitorAccess();
+    public ThreadInfo[] dumpAllThreads(boolean lockedMonitors,
+                                       boolean lockedSynchronizers) {
+        verifyDumpThreads(lockedMonitors, lockedSynchronizers);
         return dumpThreads0(null, lockedMonitors, lockedSynchronizers);
     }
 
     // VM support where maxDepth == -1 to request entire stack dump
     private static native Thread[] getThreads();
-    private static native void getThreadInfo0(long[] ids,
+    private static native void getThreadInfo1(long[] ids,
                                               int maxDepth,
                                               ThreadInfo[] result);
     private static native long getThreadTotalCpuTime0(long id);
+    private static native void getThreadTotalCpuTime1(long[] ids, long[] result);
     private static native long getThreadUserCpuTime0(long id);
+    private static native void getThreadUserCpuTime1(long[] ids, long[] result);
+    private static native void getThreadAllocatedMemory1(long[] ids, long[] result);
     private static native void setThreadCpuTimeEnabled0(boolean enable);
+    private static native void setThreadAllocatedMemoryEnabled0(boolean enable);
     private static native void setThreadContentionMonitoringEnabled0(boolean enable);
     private static native Thread[] findMonitorDeadlockedThreads0();
     private static native Thread[] findDeadlockedThreads0();
--- a/jdk/src/share/classes/sun/management/VMManagement.java	Thu Jan 20 15:23:57 2011 +0000
+++ b/jdk/src/share/classes/sun/management/VMManagement.java	Thu Jan 20 19:34:40 2011 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2011, 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
@@ -43,6 +43,8 @@
     public boolean isBootClassPathSupported();
     public boolean isObjectMonitorUsageSupported();
     public boolean isSynchronizerUsageSupported();
+    public boolean isThreadAllocatedMemorySupported();
+    public boolean isThreadAllocatedMemoryEnabled();
 
     // Class Loading Subsystem
     public long    getTotalClassCount();
--- a/jdk/src/share/classes/sun/management/VMManagementImpl.java	Thu Jan 20 15:23:57 2011 +0000
+++ b/jdk/src/share/classes/sun/management/VMManagementImpl.java	Thu Jan 20 19:34:40 2011 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2011, 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
@@ -55,6 +55,7 @@
     private static boolean bootClassPathSupport;
     private static boolean objectMonitorUsageSupport;
     private static boolean synchronizerUsageSupport;
+    private static boolean threadAllocatedMemorySupport;
 
     static {
         version = getVersion0();
@@ -95,9 +96,13 @@
         return synchronizerUsageSupport;
     }
 
+    public boolean isThreadAllocatedMemorySupported() {
+        return threadAllocatedMemorySupport;
+    }
+
     public native boolean isThreadContentionMonitoringEnabled();
     public native boolean isThreadCpuTimeEnabled();
-
+    public native boolean isThreadAllocatedMemoryEnabled();
 
     // Class Loading Subsystem
     public int    getLoadedClassCount() {
--- a/jdk/src/share/javavm/export/jmm.h	Thu Jan 20 15:23:57 2011 +0000
+++ b/jdk/src/share/javavm/export/jmm.h	Thu Jan 20 19:34:40 2011 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2011, 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
@@ -60,7 +60,8 @@
   unsigned int isBootClassPathSupported : 1;
   unsigned int isObjectMonitorUsageSupported : 1;
   unsigned int isSynchronizerUsageSupported : 1;
-  unsigned int : 24;
+  unsigned int isThreadAllocatedMemorySupported : 1;
+  unsigned int : 23;
 } jmmOptionalSupport;
 
 typedef enum {
@@ -105,7 +106,8 @@
   JMM_VERBOSE_GC                     = 21,
   JMM_VERBOSE_CLASS                  = 22,
   JMM_THREAD_CONTENTION_MONITORING   = 23,
-  JMM_THREAD_CPU_TIME                = 24
+  JMM_THREAD_CPU_TIME                = 24,
+  JMM_THREAD_ALLOCATED_MEMORY        = 25
 } jmmBoolAttribute;
 
 
@@ -213,7 +215,10 @@
   jobject      (JNICALL *GetMemoryPoolUsage)     (JNIEnv* env, jobject pool);
   jobject      (JNICALL *GetPeakMemoryPoolUsage) (JNIEnv* env, jobject pool);
 
-  void*        reserved4;
+  void         (JNICALL *GetThreadAllocatedMemory)
+                                                 (JNIEnv *env,
+                                                  jlongArray ids,
+                                                  jlongArray sizeArray);
 
   jobject      (JNICALL *GetMemoryUsage)         (JNIEnv* env, jboolean heap);
 
@@ -228,6 +233,8 @@
                                                   jlong* result);
 
   jobjectArray (JNICALL *FindCircularBlockedThreads) (JNIEnv *env);
+
+  // Not used in JDK 6 or JDK 7
   jlong        (JNICALL *GetThreadCpuTime)       (JNIEnv *env, jlong thread_id);
 
   jobjectArray (JNICALL *GetVMGlobalNames)       (JNIEnv *env);
@@ -262,14 +269,22 @@
   void         (JNICALL *GetLastGCStat)          (JNIEnv *env,
                                                   jobject mgr,
                                                   jmmGCStat *gc_stat);
-  jlong        (JNICALL *GetThreadCpuTimeWithKind) (JNIEnv *env,
-                                                    jlong thread_id,
-                                                    jboolean user_sys_cpu_time);
-  void*        reserved5;
+
+  jlong        (JNICALL *GetThreadCpuTimeWithKind)
+                                                 (JNIEnv *env,
+                                                  jlong thread_id,
+                                                  jboolean user_sys_cpu_time);
+  void         (JNICALL *GetThreadCpuTimesWithKind)
+                                                 (JNIEnv *env,
+                                                  jlongArray ids,
+                                                  jlongArray timeArray,
+                                                  jboolean user_sys_cpu_time);
+
   jint         (JNICALL *DumpHeap0)              (JNIEnv *env,
                                                   jstring outputfile,
                                                   jboolean live);
-  jobjectArray (JNICALL *FindDeadlocks)             (JNIEnv *env, jboolean object_monitors_only);
+  jobjectArray (JNICALL *FindDeadlocks)          (JNIEnv *env,
+                                                  jboolean object_monitors_only);
   void         (JNICALL *SetVMGlobal)            (JNIEnv *env,
                                                   jstring flag_name,
                                                   jvalue  new_value);
--- a/jdk/src/share/native/sun/management/ThreadImpl.c	Thu Jan 20 15:23:57 2011 +0000
+++ b/jdk/src/share/native/sun/management/ThreadImpl.c	Thu Jan 20 19:34:40 2011 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2011, 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
@@ -42,9 +42,15 @@
     jmm_interface->SetBoolAttribute(env, JMM_THREAD_CPU_TIME, flag);
 }
 
+JNIEXPORT void JNICALL
+Java_sun_management_ThreadImpl_setThreadAllocatedMemoryEnabled0
+  (JNIEnv *env, jclass cls, jboolean flag)
+{
+    jmm_interface->SetBoolAttribute(env, JMM_THREAD_ALLOCATED_MEMORY, flag);
+}
 
 JNIEXPORT void JNICALL
-Java_sun_management_ThreadImpl_getThreadInfo0
+Java_sun_management_ThreadImpl_getThreadInfo1
   (JNIEnv *env, jclass cls, jlongArray ids, jint maxDepth,
    jobjectArray infoArray)
 {
@@ -65,6 +71,14 @@
     return jmm_interface->GetThreadCpuTimeWithKind(env, tid, JNI_TRUE /* user+sys */);
 }
 
+JNIEXPORT void JNICALL
+Java_sun_management_ThreadImpl_getThreadTotalCpuTime1
+  (JNIEnv *env, jclass cls, jlongArray ids, jlongArray timeArray)
+{
+    jmm_interface->GetThreadCpuTimesWithKind(env, ids, timeArray,
+                                             JNI_TRUE /* user+sys */);
+}
+
 JNIEXPORT jlong JNICALL
 Java_sun_management_ThreadImpl_getThreadUserCpuTime0
   (JNIEnv *env, jclass cls, jlong tid)
@@ -72,6 +86,21 @@
     return jmm_interface->GetThreadCpuTimeWithKind(env, tid, JNI_FALSE /* user */);
 }
 
+JNIEXPORT void JNICALL
+Java_sun_management_ThreadImpl_getThreadUserCpuTime1
+  (JNIEnv *env, jclass cls, jlongArray ids, jlongArray timeArray)
+{
+    jmm_interface->GetThreadCpuTimesWithKind(env, ids, timeArray,
+                                             JNI_FALSE /* user */);
+}
+
+JNIEXPORT void JNICALL
+Java_sun_management_ThreadImpl_getThreadAllocatedMemory1
+  (JNIEnv *env, jclass cls, jlongArray ids, jlongArray sizeArray)
+{
+    jmm_interface->GetThreadAllocatedMemory(env, ids, sizeArray);
+}
+
 JNIEXPORT jobjectArray JNICALL
 Java_sun_management_ThreadImpl_findMonitorDeadlockedThreads0
   (JNIEnv *env, jclass cls)
--- a/jdk/src/share/native/sun/management/VMManagementImpl.c	Thu Jan 20 15:23:57 2011 +0000
+++ b/jdk/src/share/native/sun/management/VMManagementImpl.c	Thu Jan 20 19:34:40 2011 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2011, 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
@@ -92,6 +92,9 @@
         setStaticBooleanField(env, cls, "objectMonitorUsageSupport", JNI_FALSE);
         setStaticBooleanField(env, cls, "synchronizerUsageSupport", JNI_FALSE);
     }
+
+    value = mos.isThreadAllocatedMemorySupported;
+    setStaticBooleanField(env, cls, "threadAllocatedMemorySupport", value);
 }
 
 JNIEXPORT jobjectArray JNICALL
@@ -201,6 +204,13 @@
     return jmm_interface->GetBoolAttribute(env, JMM_THREAD_CPU_TIME);
 }
 
+JNIEXPORT jboolean JNICALL
+Java_sun_management_VMManagementImpl_isThreadAllocatedMemoryEnabled
+  (JNIEnv *env, jobject dummy)
+{
+    return jmm_interface->GetBoolAttribute(env, JMM_THREAD_ALLOCATED_MEMORY);
+}
+
 JNIEXPORT jint JNICALL
 Java_sun_management_VMManagementImpl_getProcessId
   (JNIEnv *env, jobject dummy)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/management/ThreadMXBean/ThreadAllocatedMemory.java	Thu Jan 20 19:34:40 2011 -0500
@@ -0,0 +1,247 @@
+/*
+ * Copyright (c) 2011, 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     6173675
+ * @summary Basic test of ThreadMXBean.getThreadAllocatedBytes
+ * @author  Paul Hohensee
+ */
+
+import java.lang.management.*;
+
+public class ThreadAllocatedMemory {
+    private static com.sun.management.ThreadMXBean mbean =
+        (com.sun.management.ThreadMXBean)ManagementFactory.getThreadMXBean();
+    private static boolean testFailed = false;
+    private static boolean done = false;
+    private static boolean done1 = false;
+    private static Object obj = new Object();
+    private static final int NUM_THREADS = 10;
+    private static Thread[] threads = new Thread[NUM_THREADS];
+    private static long[] sizes = new long[NUM_THREADS];
+
+    public static void main(String[] argv)
+        throws Exception {
+
+        if (!mbean.isThreadAllocatedMemorySupported()) {
+            return;
+        }
+
+        // disable allocated memory measurement
+        if (mbean.isThreadAllocatedMemoryEnabled()) {
+            mbean.setThreadAllocatedMemoryEnabled(false);
+        }
+
+        if (mbean.isThreadAllocatedMemoryEnabled()) {
+            throw new RuntimeException(
+                "ThreadAllocatedMemory is expected to be disabled");
+        }
+
+        Thread curThread = Thread.currentThread();
+        long id = curThread.getId();
+
+        long s = mbean.getThreadAllocatedBytes(id);
+        if (s != -1) {
+            throw new RuntimeException(
+                "Invalid ThreadAllocatedBytes returned = " +
+                s + " expected = -1");
+        }
+
+        // enable allocated memory measurement
+        if (!mbean.isThreadAllocatedMemoryEnabled()) {
+            mbean.setThreadAllocatedMemoryEnabled(true);
+        }
+
+        if (!mbean.isThreadAllocatedMemoryEnabled()) {
+            throw new RuntimeException(
+                "ThreadAllocatedMemory is expected to be enabled");
+        }
+
+        long size = mbean.getThreadAllocatedBytes(id);
+        // implementation could have started measurement when
+        // measurement was enabled, in which case size can be 0
+        if (size < 0) {
+            throw new RuntimeException(
+                "Invalid allocated bytes returned = " + size);
+        }
+
+        doit();
+
+        // Expected to be size1 >= size
+        long size1 = mbean.getThreadAllocatedBytes(id);
+        if (size1 < size) {
+            throw new RuntimeException("Allocated bytes " + size1 +
+                " expected >= " + size);
+        }
+        System.out.println(curThread.getName() +
+            " Current thread allocated bytes = " + size +
+            " allocated bytes = " + size1);
+
+
+        // start threads, wait for them to block
+        for (int i = 0; i < NUM_THREADS; i++) {
+            threads[i] = new MyThread("MyThread-" + i);
+            threads[i].start();
+        }
+
+        // threads block after doing some allocation
+        waitUntilThreadBlocked();
+
+        for (int i = 0; i < NUM_THREADS; i++) {
+            sizes[i] = mbean.getThreadAllocatedBytes(threads[i].getId());
+        }
+
+        // let threads go and do some more allocation
+        synchronized (obj) {
+            done = true;
+            obj.notifyAll();
+        }
+
+        // wait for threads to get going again.  we don't care if we
+        // catch them in mid-execution or if some of them haven't
+        // restarted after we're done sleeping.
+        goSleep(400);
+
+        for (int i = 0; i < NUM_THREADS; i++) {
+            long newSize = mbean.getThreadAllocatedBytes(threads[i].getId());
+            if (sizes[i] > newSize) {
+                throw new RuntimeException("TEST FAILED: " +
+                    threads[i].getName() +
+                    " previous allocated bytes = " + sizes[i] +
+                    " > current allocated bytes = " + newSize);
+            }
+            System.out.println(threads[i].getName() +
+                " Previous allocated bytes = " + sizes[i] +
+                " Current allocated bytes = " + newSize);
+        }
+
+        // let threads exit
+        synchronized (obj) {
+            done1 = true;
+            obj.notifyAll();
+        }
+
+        for (int i = 0; i < NUM_THREADS; i++) {
+            try {
+                threads[i].join();
+            } catch (InterruptedException e) {
+                System.out.println("Unexpected exception is thrown.");
+                e.printStackTrace(System.out);
+                testFailed = true;
+                break;
+            }
+        }
+        if (testFailed) {
+            throw new RuntimeException("TEST FAILED");
+        }
+
+        System.out.println("Test passed");
+    }
+
+
+    private static void goSleep(long ms) throws Exception {
+        try {
+            Thread.sleep(ms);
+        } catch (InterruptedException e) {
+            System.out.println("Unexpected exception is thrown.");
+            throw e;
+        }
+    }
+
+    private static void waitUntilThreadBlocked()
+        throws Exception {
+        int count = 0;
+        while (count != NUM_THREADS) {
+            goSleep(100);
+            count = 0;
+            for (int i = 0; i < NUM_THREADS; i++) {
+                ThreadInfo info = mbean.getThreadInfo(threads[i].getId());
+                if (info.getThreadState() == Thread.State.WAITING) {
+                    count++;
+                }
+            }
+        }
+    }
+
+    public static void doit() {
+        String tmp = "";
+        long hashCode = 0;
+        for (int counter = 0; counter < 1000; counter++) {
+            tmp += counter;
+            hashCode = tmp.hashCode();
+        }
+        System.out.println(Thread.currentThread().getName() +
+                           " hashcode: " + hashCode);
+    }
+
+    static class MyThread extends Thread {
+        public MyThread(String name) {
+            super(name);
+        }
+
+        public void run() {
+            ThreadAllocatedMemory.doit();
+
+            synchronized (obj) {
+                while (!done) {
+                    try {
+                        obj.wait();
+                    } catch (InterruptedException e) {
+                        System.out.println("Unexpected exception is thrown.");
+                        e.printStackTrace(System.out);
+                        testFailed = true;
+                        break;
+                    }
+                }
+            }
+
+            long size1 = mbean.getThreadAllocatedBytes(getId());
+            ThreadAllocatedMemory.doit();
+            long size2 = mbean.getThreadAllocatedBytes(getId());
+
+            System.out.println(getName() + ": " +
+                "ThreadAllocatedBytes  = " + size1 +
+                " ThreadAllocatedBytes  = " + size2);
+
+            if (size1 > size2) {
+                throw new RuntimeException("TEST FAILED: " + getName() +
+                    " ThreadAllocatedBytes = " + size1 +
+                    " > ThreadAllocatedBytes = " + size2);
+            }
+
+            synchronized (obj) {
+                while (!done1) {
+                    try {
+                        obj.wait();
+                    } catch (InterruptedException e) {
+                        System.out.println("Unexpected exception is thrown.");
+                        e.printStackTrace(System.out);
+                        testFailed = true;
+                        break;
+                    }
+                }
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/management/ThreadMXBean/ThreadAllocatedMemoryArray.java	Thu Jan 20 19:34:40 2011 -0500
@@ -0,0 +1,249 @@
+/*
+ * Copyright (c) 2011, 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     6173675
+ * @summary Basic test of ThreadMXBean.getThreadAllocatedBytes(long[])
+ * @author  Paul Hohensee
+ */
+
+import java.lang.management.*;
+
+public class ThreadAllocatedMemoryArray {
+    private static com.sun.management.ThreadMXBean mbean =
+        (com.sun.management.ThreadMXBean)ManagementFactory.getThreadMXBean();
+    private static boolean testFailed = false;
+    private static boolean done = false;
+    private static boolean done1 = false;
+    private static Object obj = new Object();
+    private static final int NUM_THREADS = 10;
+    private static Thread[] threads = new Thread[NUM_THREADS];
+
+    public static void main(String[] argv)
+        throws Exception {
+
+        if (!mbean.isThreadAllocatedMemorySupported()) {
+            return;
+        }
+
+
+        // start threads, wait for them to block
+        long[] ids = new long[NUM_THREADS];
+
+        for (int i = 0; i < NUM_THREADS; i++) {
+            threads[i] = new MyThread("MyThread-" + i);
+            threads[i].start();
+            ids[i] = threads[i].getId();
+        }
+
+        waitUntilThreadBlocked();
+
+
+        // disable allocated memory measurement
+        if (mbean.isThreadAllocatedMemoryEnabled()) {
+            mbean.setThreadAllocatedMemoryEnabled(false);
+        }
+
+        if (mbean.isThreadAllocatedMemoryEnabled()) {
+            throw new RuntimeException(
+                "ThreadAllocatedMemory is expected to be disabled");
+        }
+
+        long sizes[] = mbean.getThreadAllocatedBytes(ids);
+
+        if (sizes == null) {
+          throw new RuntimeException("Null ThreadAllocatedBytes array returned");
+        }
+
+        for (int i = 0; i < NUM_THREADS; i++) {
+            long s = sizes[i];
+            if (s != -1) {
+                throw new RuntimeException(
+                    "Invalid ThreadAllocatedBytes returned for thread " +
+                    threads[i].getName() + " = " +  s + " expected = -1");
+            }
+        }
+
+        // Enable allocated memory measurement
+        if (!mbean.isThreadAllocatedMemoryEnabled()) {
+            mbean.setThreadAllocatedMemoryEnabled(true);
+        }
+
+        if (!mbean.isThreadAllocatedMemoryEnabled()) {
+            throw new RuntimeException(
+                "ThreadAllocatedMemory is expected to be enabled");
+        }
+
+        sizes = mbean.getThreadAllocatedBytes(ids);
+
+        for (int i = 0; i < NUM_THREADS; i++) {
+            long s = sizes[i];
+            if (s < 0) {
+                throw new RuntimeException(
+                    "Invalid allocated bytes returned for thread " +
+                    threads[i].getName() + " = " + s);
+            }
+        }
+
+        // let threads go and do some more allocation
+        synchronized (obj) {
+            done = true;
+            obj.notifyAll();
+        }
+
+        // wait for threads to get going again.  we don't care if we
+        // catch them in mid-execution or if some of them haven't
+        // restarted after we're done sleeping.
+        goSleep(400);
+
+        long[] sizes1 = mbean.getThreadAllocatedBytes(ids);
+
+        for (int i = 0; i < NUM_THREADS; i++) {
+            long newSize = sizes1[i];
+            if (sizes[i] > newSize) {
+                throw new RuntimeException("TEST FAILED: " +
+                    threads[i].getName() +
+                    " previous allocated bytes = " + sizes[i] +
+                    " > current allocated bytes = " + newSize);
+            }
+            System.out.println(threads[i].getName() +
+                " Previous allocated bytes = " + sizes[i] +
+                " Current allocated bytes = " + newSize);
+        }
+
+        try {
+            sizes = mbean.getThreadAllocatedBytes(null);
+        } catch (NullPointerException e) {
+            System.out.println(
+                "Caught expected NullPointerException: " + e.getMessage());
+        }
+
+        try {
+            ids[0] = 0;
+            sizes = mbean.getThreadAllocatedBytes(ids);
+        } catch (IllegalArgumentException e) {
+            System.out.println(
+                "Caught expected IllegalArgumentException: " + e.getMessage());
+        }
+
+
+        // let threads exit
+        synchronized (obj) {
+            done1 = true;
+            obj.notifyAll();
+        }
+
+        for (int i = 0; i < NUM_THREADS; i++) {
+            try {
+                threads[i].join();
+            } catch (InterruptedException e) {
+                System.out.println("Unexpected exception is thrown.");
+                e.printStackTrace(System.out);
+                testFailed = true;
+                break;
+            }
+        }
+
+        if (testFailed) {
+            throw new RuntimeException("TEST FAILED");
+        }
+
+        System.out.println("Test passed");
+    }
+
+
+    private static void goSleep(long ms) throws Exception {
+        try {
+            Thread.sleep(ms);
+        } catch (InterruptedException e) {
+            System.out.println("Unexpected exception is thrown.");
+            throw e;
+        }
+    }
+
+    private static void waitUntilThreadBlocked()
+        throws Exception {
+        int count = 0;
+        while (count != NUM_THREADS) {
+            goSleep(100);
+            count = 0;
+            for (int i = 0; i < NUM_THREADS; i++) {
+                ThreadInfo info = mbean.getThreadInfo(threads[i].getId());
+                if (info.getThreadState() == Thread.State.WAITING) {
+                    count++;
+                }
+            }
+        }
+    }
+
+    public static void doit() {
+        String tmp = "";
+        long hashCode = 0;
+        for (int counter = 0; counter < 1000; counter++) {
+            tmp += counter;
+            hashCode = tmp.hashCode();
+        }
+        System.out.println(Thread.currentThread().getName() +
+                           " hashcode: " + hashCode);
+    }
+
+    static class MyThread extends Thread {
+        public MyThread(String name) {
+            super(name);
+        }
+
+        public void run() {
+            ThreadAllocatedMemoryArray.doit();
+
+            synchronized (obj) {
+                while (!done) {
+                    try {
+                        obj.wait();
+                    } catch (InterruptedException e) {
+                        System.out.println("Unexpected exception is thrown.");
+                        e.printStackTrace(System.out);
+                        testFailed = true;
+                        break;
+                    }
+                }
+            }
+
+            ThreadAllocatedMemoryArray.doit();
+
+            synchronized (obj) {
+                while (!done1) {
+                    try {
+                        obj.wait();
+                    } catch (InterruptedException e) {
+                        System.out.println("Unexpected exception is thrown.");
+                        e.printStackTrace(System.out);
+                        testFailed = true;
+                        break;
+                    }
+                }
+            }
+
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/management/ThreadMXBean/ThreadCpuTimeArray.java	Thu Jan 20 19:34:40 2011 -0500
@@ -0,0 +1,259 @@
+/*
+ * Copyright (c) 2011, 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     6173675
+ * @summary Basic test of ThreadMXBean.getThreadCpuTime(long[]) and
+ *          getThreadUserTime(long[]).
+ * @author  Paul Hohensee
+ */
+
+import java.lang.management.*;
+
+public class ThreadCpuTimeArray {
+    private static com.sun.management.ThreadMXBean mbean =
+        (com.sun.management.ThreadMXBean)ManagementFactory.getThreadMXBean();
+    private static boolean testFailed = false;
+    private static boolean done = false;
+    private static Object obj = new Object();
+    private static final int NUM_THREADS = 10;
+    private static Thread[] threads = new Thread[NUM_THREADS];
+
+    // careful about this value
+    private static final int DELTA = 100;
+
+    public static void main(String[] argv)
+        throws Exception {
+
+        if (!mbean.isThreadCpuTimeSupported()) {
+            return;
+        }
+
+
+        // disable CPU time
+        if (mbean.isThreadCpuTimeEnabled()) {
+            mbean.setThreadCpuTimeEnabled(false);
+        }
+
+        if (mbean.isThreadCpuTimeEnabled()) {
+            throw new RuntimeException("ThreadCpuTime is expected to be disabled");
+        }
+
+        // start threads, wait for them to block
+        long[] ids = new long[NUM_THREADS];
+
+        for (int i = 0; i < NUM_THREADS; i++) {
+            threads[i] = new MyThread("MyThread-" + i);
+            threads[i].start();
+            ids[i] = threads[i].getId();
+        }
+
+        // threads block after doing some computation
+        waitUntilThreadBlocked();
+
+
+        long times[] = mbean.getThreadCpuTime(ids);
+        long userTimes[] = mbean.getThreadUserTime(ids);
+
+        if (times == null) {
+            throw new RuntimeException("Null ThreadCpuTime array returned");
+        }
+
+        for (int i = 0; i < NUM_THREADS; i++) {
+            long t = times[i];
+            if (t != -1) {
+                throw new RuntimeException(
+                    "Invalid ThreadCpuTime returned for thread " +
+                    threads[i].getName() + " = " +  t + " expected = -1");
+            }
+            long ut = userTimes[i];
+            if (ut != -1) {
+                throw new RuntimeException(
+                    "Invalid ThreadUserTime returned for thread " +
+                    threads[i].getName() + " = " +  ut + " expected = -1");
+            }
+        }
+
+
+        // Enable CPU Time measurement
+        if (!mbean.isThreadCpuTimeEnabled()) {
+            mbean.setThreadCpuTimeEnabled(true);
+        }
+
+        if (!mbean.isThreadCpuTimeEnabled()) {
+            throw new RuntimeException("ThreadCpuTime is expected to be enabled");
+        }
+
+        times = mbean.getThreadCpuTime(ids);
+        userTimes = mbean.getThreadUserTime(ids);
+
+        goSleep(200);
+
+        for (int i = 0; i < NUM_THREADS; i++) {
+            long t = times[i];
+            if (t < 0) {
+                throw new RuntimeException(
+                    "Invalid CPU time returned for thread " +
+                    threads[i].getName() + " = " + t);
+            }
+            long ut = userTimes[i];
+            if (ut < 0) {
+                throw new RuntimeException(
+                    "Invalid user time returned for thread " +
+                    threads[i].getName() + " = " + ut);
+            }
+        }
+
+        long[] times1 = mbean.getThreadCpuTime(ids);
+        long[] userTimes1 = mbean.getThreadUserTime(ids);
+
+        for (int i = 0; i < NUM_THREADS; i++) {
+            long newTime = times1[i];
+            long newUserTime = userTimes1[i];
+
+            if (times[i] > newTime) {
+                throw new RuntimeException("TEST FAILED: " +
+                    threads[i].getName() +
+                    " previous CPU time = " + times[i] +
+                    " > current CPU time = " + newTime);
+            }
+            if ((times[i] + DELTA) < newTime) {
+                throw new RuntimeException("TEST FAILED: " +
+                    threads[i].getName() +
+                    " CPU time = " + newTime +
+                    " previous CPU time " + times[i] +
+                    " out of expected range");
+            }
+
+            System.out.println(threads[i].getName() +
+                " Previous Cpu Time = " + times[i] +
+                " Current CPU time = " + newTime);
+
+            System.out.println(threads[i].getName() +
+                " Previous User Time = " + userTimes[i] +
+                " Current User time = " + newUserTime);
+        }
+
+
+        try {
+            times = mbean.getThreadCpuTime(null);
+        } catch (NullPointerException e) {
+            System.out.println(
+                "Caught expected NullPointerException: " + e.getMessage());
+        }
+
+        try {
+            ids[0] = 0;
+            times = mbean.getThreadCpuTime(ids);
+        } catch (IllegalArgumentException e) {
+            System.out.println(
+                "Caught expected IllegalArgumentException: " + e.getMessage());
+        }
+
+
+        // let threads exit
+        synchronized (obj) {
+            done = true;
+            obj.notifyAll();
+        }
+
+        for (int i = 0; i < NUM_THREADS; i++) {
+            try {
+                threads[i].join();
+            } catch (InterruptedException e) {
+                System.out.println("Unexpected exception is thrown.");
+                e.printStackTrace(System.out);
+                testFailed = true;
+                break;
+            }
+        }
+
+        if (testFailed) {
+            throw new RuntimeException("TEST FAILED");
+        }
+
+        System.out.println("Test passed");
+    }
+
+
+    private static void goSleep(long ms) throws Exception {
+        try {
+            Thread.sleep(ms);
+        } catch (InterruptedException e) {
+            System.out.println("Unexpected exception is thrown.");
+            throw e;
+        }
+    }
+
+    private static void waitUntilThreadBlocked()
+        throws Exception {
+        int count = 0;
+        while (count != NUM_THREADS) {
+            goSleep(100);
+            count = 0;
+            for (int i = 0; i < NUM_THREADS; i++) {
+                ThreadInfo info = mbean.getThreadInfo(threads[i].getId());
+                if (info.getThreadState() == Thread.State.WAITING) {
+                    count++;
+                }
+            }
+        }
+    }
+
+    public static void doit() {
+        double sum = 0;
+        for (int i = 0; i < 5000; i++) {
+           double r = Math.random();
+           double x = Math.pow(3, r);
+           sum += x - r;
+        }
+        System.out.println(Thread.currentThread().getName() +
+                           " sum = " + sum);
+    }
+
+    static class MyThread extends Thread {
+        public MyThread(String name) {
+            super(name);
+        }
+
+        public void run() {
+            ThreadCpuTimeArray.doit();
+
+            synchronized (obj) {
+                while (!done) {
+                    try {
+                        obj.wait();
+                    } catch (InterruptedException e) {
+                        System.out.println("Unexpected exception is thrown.");
+                        e.printStackTrace(System.out);
+                        testFailed = true;
+                        break;
+                    }
+                }
+            }
+
+            ThreadCpuTimeArray.doit();
+        }
+    }
+}