1 /*
  2  * Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.
  8  *
  9  * This code is distributed in the hope that it will be useful, but WITHOUT
 10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 12  * version 2 for more details (a copy is included in the LICENSE file that
 13  * accompanied this code).
 14  *
 15  * You should have received a copy of the GNU General Public License version
 16  * 2 along with this work; if not, write to the Free Software Foundation,
 17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 18  *
 19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 20  * or visit www.oracle.com if you need additional information or have any
 21  * questions.
 22  */
 23 
 24 /*
 25  * @test
 26  * @bug     6173675
 27  * @key randomness
 28  * @summary Basic test of ThreadMXBean.getThreadCpuTime(long[]) and
 29  *          getThreadUserTime(long[]).
 30  * @author  Paul Hohensee
 31  * @requires vm.compMode != "Xcomp"
 32  */
 33 
 34 import java.lang.management.*;
 35 
 36 public class ThreadCpuTimeArray {
 37     private static com.sun.management.ThreadMXBean mbean =
 38         (com.sun.management.ThreadMXBean)ManagementFactory.getThreadMXBean();
 39     private static boolean testFailed = false;
 40     private static boolean done = false;
 41     private static Object obj = new Object();
 42     private static final int NUM_THREADS = 10;
 43     private static Thread[] threads = new Thread[NUM_THREADS];
 44 
 45     // careful about this value
 46     private static final int DELTA = 100;
 47 
 48     public static void main(String[] argv)
 49         throws Exception {
 50 
 51         if (!mbean.isThreadCpuTimeSupported()) {
 52             return;
 53         }
 54 
 55 
 56         // disable CPU time
 57         if (mbean.isThreadCpuTimeEnabled()) {
 58             mbean.setThreadCpuTimeEnabled(false);
 59         }
 60 
 61         if (mbean.isThreadCpuTimeEnabled()) {
 62             throw new RuntimeException("ThreadCpuTime is expected to be disabled");
 63         }
 64 
 65         // start threads, wait for them to block
 66         long[] ids = new long[NUM_THREADS];
 67 
 68         for (int i = 0; i < NUM_THREADS; i++) {
 69             threads[i] = new MyThread("MyThread-" + i);
 70             threads[i].start();
 71             ids[i] = threads[i].getId();
 72         }
 73 
 74         // threads block after doing some computation
 75         waitUntilThreadBlocked();
 76 
 77 
 78         long times[] = mbean.getThreadCpuTime(ids);
 79         long userTimes[] = mbean.getThreadUserTime(ids);
 80 
 81         if (times == null) {
 82             throw new RuntimeException("Null ThreadCpuTime array returned");
 83         }
 84 
 85         for (int i = 0; i < NUM_THREADS; i++) {
 86             long t = times[i];
 87             if (t != -1) {
 88                 throw new RuntimeException(
 89                     "Invalid ThreadCpuTime returned for thread " +
 90                     threads[i].getName() + " = " +  t + " expected = -1");
 91             }
 92             long ut = userTimes[i];
 93             if (ut != -1) {
 94                 throw new RuntimeException(
 95                     "Invalid ThreadUserTime returned for thread " +
 96                     threads[i].getName() + " = " +  ut + " expected = -1");
 97             }
 98         }
 99 
100 
101         // Enable CPU Time measurement
102         if (!mbean.isThreadCpuTimeEnabled()) {
103             mbean.setThreadCpuTimeEnabled(true);
104         }
105 
106         if (!mbean.isThreadCpuTimeEnabled()) {
107             throw new RuntimeException("ThreadCpuTime is expected to be enabled");
108         }
109 
110         times = mbean.getThreadCpuTime(ids);
111         userTimes = mbean.getThreadUserTime(ids);
112 
113         goSleep(200);
114 
115         for (int i = 0; i < NUM_THREADS; i++) {
116             long t = times[i];
117             if (t < 0) {
118                 throw new RuntimeException(
119                     "Invalid CPU time returned for thread " +
120                     threads[i].getName() + " = " + t);
121             }
122             long ut = userTimes[i];
123             if (ut < 0) {
124                 throw new RuntimeException(
125                     "Invalid user time returned for thread " +
126                     threads[i].getName() + " = " + ut);
127             }
128         }
129 
130         long[] times1 = mbean.getThreadCpuTime(ids);
131         long[] userTimes1 = mbean.getThreadUserTime(ids);
132 
133         for (int i = 0; i < NUM_THREADS; i++) {
134             long newTime = times1[i];
135             long newUserTime = userTimes1[i];
136 
137             if (times[i] > newTime) {
138                 throw new RuntimeException("TEST FAILED: " +
139                     threads[i].getName() +
140                     " previous CPU time = " + times[i] +
141                     " > current CPU time = " + newTime);
142             }
143             if ((times[i] + DELTA) < newTime) {
144                 throw new RuntimeException("TEST FAILED: " +
145                     threads[i].getName() +
146                     " CPU time = " + newTime +
147                     " previous CPU time " + times[i] +
148                     " out of expected range");
149             }
150 
151             System.out.println(threads[i].getName() +
152                 " Previous Cpu Time = " + times[i] +
153                 " Current CPU time = " + newTime);
154 
155             System.out.println(threads[i].getName() +
156                 " Previous User Time = " + userTimes[i] +
157                 " Current User time = " + newUserTime);
158         }
159 
160 
161         try {
162             times = mbean.getThreadCpuTime(null);
163         } catch (NullPointerException e) {
164             System.out.println(
165                 "Caught expected NullPointerException: " + e.getMessage());
166         }
167 
168         try {
169             ids[0] = 0;
170             times = mbean.getThreadCpuTime(ids);
171         } catch (IllegalArgumentException e) {
172             System.out.println(
173                 "Caught expected IllegalArgumentException: " + e.getMessage());
174         }
175 
176 
177         // let threads exit
178         synchronized (obj) {
179             done = true;
180             obj.notifyAll();
181         }
182 
183         for (int i = 0; i < NUM_THREADS; i++) {
184             try {
185                 threads[i].join();
186             } catch (InterruptedException e) {
187                 System.out.println("Unexpected exception is thrown.");
188                 e.printStackTrace(System.out);
189                 testFailed = true;
190                 break;
191             }
192         }
193 
194         if (testFailed) {
195             throw new RuntimeException("TEST FAILED");
196         }
197 
198         System.out.println("Test passed");
199     }
200 
201 
202     private static void goSleep(long ms) throws Exception {
203         try {
204             Thread.sleep(ms);
205         } catch (InterruptedException e) {
206             System.out.println("Unexpected exception is thrown.");
207             throw e;
208         }
209     }
210 
211     private static void waitUntilThreadBlocked()
212         throws Exception {
213         int count = 0;
214         while (count != NUM_THREADS) {
215             goSleep(100);
216             count = 0;
217             for (int i = 0; i < NUM_THREADS; i++) {
218                 ThreadInfo info = mbean.getThreadInfo(threads[i].getId());
219                 if (info.getThreadState() == Thread.State.WAITING) {
220                     count++;
221                 }
222             }
223         }
224     }
225 
226     public static void doit() {
227         double sum = 0;
228         for (int i = 0; i < 5000; i++) {
229            double r = Math.random();
230            double x = Math.pow(3, r);
231            sum += x - r;
232         }
233         System.out.println(Thread.currentThread().getName() +
234                            " sum = " + sum);
235     }
236 
237     static class MyThread extends Thread {
238         public MyThread(String name) {
239             super(name);
240         }
241 
242         public void run() {
243             ThreadCpuTimeArray.doit();
244 
245             synchronized (obj) {
246                 while (!done) {
247                     try {
248                         obj.wait();
249                     } catch (InterruptedException e) {
250                         System.out.println("Unexpected exception is thrown.");
251                         e.printStackTrace(System.out);
252                         testFailed = true;
253                         break;
254                     }
255                 }
256             }
257 
258             ThreadCpuTimeArray.doit();
259         }
260     }
261 }