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
--- 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();
+ }
+ }
+}