diff --git a/make/java/management/mapfile-vers b/make/java/management/mapfile-vers index a9d931d78bcf79e2c98dfa67783e3b1f146d1d2b..d84f061a1750b1c3f5b68590b4f2be23e7e9093d 100644 --- a/make/java/management/mapfile-vers +++ b/make/java/management/mapfile-vers @@ -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 @@ SUNWprivate_1.1 { 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 @@ SUNWprivate_1.1 { Java_sun_management_VMManagementImpl_initOptionalSupportFields; Java_sun_management_VMManagementImpl_isThreadContentionMonitoringEnabled; Java_sun_management_VMManagementImpl_isThreadCpuTimeEnabled; + Java_sun_management_VMManagementImpl_isThreadAllocatedMemoryEnabled; JNI_OnLoad; local: *; diff --git a/src/share/classes/com/sun/management/ThreadMXBean.java b/src/share/classes/com/sun/management/ThreadMXBean.java new file mode 100644 index 0000000000000000000000000000000000000000..f5a9a5b9a0d199a2caa4f84dae597c559a91b29c --- /dev/null +++ b/src/share/classes/com/sun/management/ThreadMXBean.java @@ -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. + *

+ * 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. + *

+ * 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. + *

+ * 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. + *

+ * 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. + *

+ * 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. + *

+ * 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); +} diff --git a/src/share/classes/sun/management/ThreadImpl.java b/src/share/classes/sun/management/ThreadImpl.java index 19f4bf7a2af0405fbb33c77eb7485a3f2d4931d5..4eb0914371962329b6ae69c4d466c58a184ea06f 100644 --- a/src/share/classes/sun/management/ThreadImpl.java +++ b/src/share/classes/sun/management/ThreadImpl.java @@ -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 @@ import javax.management.ObjectName; * 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 @@ class ThreadImpl implements ThreadMXBean { ThreadImpl(VMManagement vm) { this.jvm = vm; this.cpuTimeEnabled = jvm.isThreadCpuTimeEnabled(); + this.allocatedMemoryEnabled = jvm.isThreadAllocatedMemoryEnabled(); } public int getThreadCount() { @@ -91,6 +92,10 @@ class ThreadImpl implements ThreadMXBean { return jvm.isCurrentThreadCpuTimeSupported(); } + public boolean isThreadAllocatedMemorySupported() { + return jvm.isThreadAllocatedMemorySupported(); + } + public boolean isThreadCpuTimeEnabled() { if (!isThreadCpuTimeSupported() && !isCurrentThreadCpuTimeSupported()) { @@ -100,6 +105,14 @@ class ThreadImpl implements ThreadMXBean { 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 @@ class ThreadImpl implements ThreadMXBean { } 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 @@ class ThreadImpl implements ThreadMXBean { } 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 @@ class ThreadImpl implements ThreadMXBean { 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 @@ class ThreadImpl implements ThreadMXBean { 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,116 +200,166 @@ class ThreadImpl implements ThreadMXBean { } } - 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) { + long[] ids = new long[1]; + ids[0] = id; + final long[] times = getThreadCpuTime(ids); + return times[0]; + } + + private boolean verifyThreadCpuTime(long[] ids) { + verifyThreadIds(ids); + // check if Thread CPU time measurement is supported. if (!isThreadCpuTimeSupported() && !isCurrentThreadCpuTimeSupported()) { throw new UnsupportedOperationException( - "Thread CPU Time Measurement is not supported."); + "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."); + 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(); + } - if (!isThreadCpuTimeEnabled()) { - return -1; - } + public long[] getThreadCpuTime(long[] ids) { + boolean verified = verifyThreadCpuTime(ids); - if (id == Thread.currentThread().getId()) { - // current thread - return getThreadTotalCpuTime0(0); - } else { - return getThreadTotalCpuTime0(id); + 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; + } + getThreadTotalCpuTime0(id); + } else { + getThreadTotalCpuTime1(ids, times); + } } + return times; } public long getCurrentThreadUserTime() { - // check if Thread CPU time measurement is supported. - if (!isCurrentThreadCpuTimeSupported()) { - throw new UnsupportedOperationException( - "Current thread CPU time measurement is not supported."); + if (verifyCurrentThreadCpuTime()) { + return getThreadUserCpuTime0(0); } + return -1; + } - if (!isThreadCpuTimeEnabled()) { - return -1; - } + public long getThreadUserTime(long id) { + long[] ids = new long[1]; + ids[0] = id; + final long[] times = getThreadUserTime(ids); + return times[0]; + } - return getThreadUserCpuTime0(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 long getThreadUserTime(long id) { - // check if Thread CPU time measurement is supported. + public void setThreadCpuTimeEnabled(boolean enable) { if (!isThreadCpuTimeSupported() && !isCurrentThreadCpuTimeSupported()) { throw new UnsupportedOperationException( - "Thread CPU time measurement is not supported."); + "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."); + Util.checkControlAccess(); + synchronized (this) { + if (cpuTimeEnabled != enable) { + // notify VM of the state change + setThreadCpuTimeEnabled0(enable); + cpuTimeEnabled = enable; } } + } - if (id <= 0) { - throw new IllegalArgumentException( - "Invalid thread ID parameter: " + id); - } + public long getThreadAllocatedBytes(long id) { + long[] ids = new long[1]; + ids[0] = id; + final long[] sizes = getThreadAllocatedBytes(ids); + return sizes[0]; + } - if (!isThreadCpuTimeEnabled()) { - return -1; - } + private boolean verifyThreadAllocatedMemory(long[] ids) { + verifyThreadIds(ids); - if (id == Thread.currentThread().getId()) { - // current thread - return getThreadUserCpuTime0(0); - } else { - return getThreadUserCpuTime0(id); + // 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); - public void setThreadCpuTimeEnabled(boolean enable) { - if (!isThreadCpuTimeSupported() && - !isCurrentThreadCpuTimeSupported()) { + 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 CPU time measurement is not supported"); + "Thread allocated memory measurement is not supported."); } Util.checkControlAccess(); synchronized (this) { - if (cpuTimeEnabled != enable) { - // update VM of the state change - setThreadCpuTimeEnabled0(enable); - cpuTimeEnabled = enable; + if (allocatedMemoryEnabled != enable) { + // notify VM of the state change + setThreadAllocatedMemoryEnabled0(enable); + allocatedMemoryEnabled = enable; } } } @@ -356,49 +414,47 @@ class ThreadImpl implements ThreadMXBean { 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(); - return dumpThreads0(ids, lockedMonitors, lockedSynchronizers); } + 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(); diff --git a/src/share/classes/sun/management/VMManagement.java b/src/share/classes/sun/management/VMManagement.java index 81d6e8015550ba0a08eeb0fc32e827022617e75d..607f6cf88aa03155be0720ba04112b46bdb38b71 100644 --- a/src/share/classes/sun/management/VMManagement.java +++ b/src/share/classes/sun/management/VMManagement.java @@ -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 interface VMManagement { public boolean isBootClassPathSupported(); public boolean isObjectMonitorUsageSupported(); public boolean isSynchronizerUsageSupported(); + public boolean isThreadAllocatedMemorySupported(); + public boolean isThreadAllocatedMemoryEnabled(); // Class Loading Subsystem public long getTotalClassCount(); diff --git a/src/share/classes/sun/management/VMManagementImpl.java b/src/share/classes/sun/management/VMManagementImpl.java index fe0ec0e557c691b190ff2bb6e2f3957d0b1e4b49..d5b00ea117f61b5ca6b973de12ccfdd08e7fa8e8 100644 --- a/src/share/classes/sun/management/VMManagementImpl.java +++ b/src/share/classes/sun/management/VMManagementImpl.java @@ -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 @@ class VMManagementImpl implements VMManagement { private static boolean bootClassPathSupport; private static boolean objectMonitorUsageSupport; private static boolean synchronizerUsageSupport; + private static boolean threadAllocatedMemorySupport; static { version = getVersion0(); @@ -95,9 +96,13 @@ class VMManagementImpl implements VMManagement { 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() { diff --git a/src/share/javavm/export/jmm.h b/src/share/javavm/export/jmm.h index e25de8bbb77697883da6bdb9a44d45473c031c94..df08124e56c508bbb606a14f2c87ff230a69d519 100644 --- a/src/share/javavm/export/jmm.h +++ b/src/share/javavm/export/jmm.h @@ -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 @@ typedef struct { 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 @@ typedef enum { 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 @@ typedef struct jmmInterface_1_ { 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 @@ typedef struct jmmInterface_1_ { 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 @@ typedef struct jmmInterface_1_ { 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); diff --git a/src/share/native/sun/management/ThreadImpl.c b/src/share/native/sun/management/ThreadImpl.c index 7ffdb351b13b694f49c917bdf15c6101d317ad25..9e1baadf15cba64af682741e8f7d39d392b72429 100644 --- a/src/share/native/sun/management/ThreadImpl.c +++ b/src/share/native/sun/management/ThreadImpl.c @@ -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 @@ Java_sun_management_ThreadImpl_setThreadCpuTimeEnabled0 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 @@ Java_sun_management_ThreadImpl_getThreadTotalCpuTime0 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 @@ Java_sun_management_ThreadImpl_getThreadUserCpuTime0 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) diff --git a/src/share/native/sun/management/VMManagementImpl.c b/src/share/native/sun/management/VMManagementImpl.c index a7cb4b35e658d34e7119787392d033f43838f233..295d93c34f55fc51a4ddc7a5c1e1eb912245aa8f 100644 --- a/src/share/native/sun/management/VMManagementImpl.c +++ b/src/share/native/sun/management/VMManagementImpl.c @@ -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 @@ Java_sun_management_VMManagementImpl_initOptionalSupportFields 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 @@ Java_sun_management_VMManagementImpl_isThreadCpuTimeEnabled 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) diff --git a/test/com/sun/management/ThreadMXBean/ThreadAllocatedMemory.java b/test/com/sun/management/ThreadMXBean/ThreadAllocatedMemory.java new file mode 100644 index 0000000000000000000000000000000000000000..6a230c77eed6b3cec5d1aa28118f30e3652fcdcb --- /dev/null +++ b/test/com/sun/management/ThreadMXBean/ThreadAllocatedMemory.java @@ -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; + } + } + } + } + } +} diff --git a/test/com/sun/management/ThreadMXBean/ThreadAllocatedMemoryArray.java b/test/com/sun/management/ThreadMXBean/ThreadAllocatedMemoryArray.java new file mode 100644 index 0000000000000000000000000000000000000000..980189098cb483b95f74f62a13d666ad51104229 --- /dev/null +++ b/test/com/sun/management/ThreadMXBean/ThreadAllocatedMemoryArray.java @@ -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; + } + } + } + + } + } +} diff --git a/test/com/sun/management/ThreadMXBean/ThreadCpuTimeArray.java b/test/com/sun/management/ThreadMXBean/ThreadCpuTimeArray.java new file mode 100644 index 0000000000000000000000000000000000000000..67dea226bd11cddeab952b8c98fa2e4c6c2ca28b --- /dev/null +++ b/test/com/sun/management/ThreadMXBean/ThreadCpuTimeArray.java @@ -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(); + } + } +}