1 /*
   2  * Copyright (c) 2011, 2015, 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  * @summary Basic test of ThreadMXBean.getThreadAllocatedBytes(long[])
  28  * @author  Paul Hohensee
  29  * @modules jdk.management
  30  */
  31 
  32 import java.lang.management.*;
  33 
  34 public class ThreadAllocatedMemoryArray {
  35     private static com.sun.management.ThreadMXBean mbean =
  36         (com.sun.management.ThreadMXBean)ManagementFactory.getThreadMXBean();
  37     private static boolean testFailed = false;
  38     private static boolean done = false;
  39     private static boolean done1 = false;
  40     private static Object obj = new Object();
  41     private static final int NUM_THREADS = 10;
  42     private static Thread[] threads = new Thread[NUM_THREADS];
  43 
  44     public static void main(String[] argv)
  45         throws Exception {
  46 
  47         if (!mbean.isThreadAllocatedMemorySupported()) {
  48             return;
  49         }
  50 
  51 
  52         // start threads, wait for them to block
  53         long[] ids = new long[NUM_THREADS];
  54 
  55         for (int i = 0; i < NUM_THREADS; i++) {
  56             threads[i] = new MyThread("MyThread-" + i);
  57             threads[i].start();
  58             ids[i] = threads[i].getId();
  59         }
  60 
  61         waitUntilThreadBlocked();
  62 
  63 
  64         // disable allocated memory measurement
  65         if (mbean.isThreadAllocatedMemoryEnabled()) {
  66             mbean.setThreadAllocatedMemoryEnabled(false);
  67         }
  68 
  69         if (mbean.isThreadAllocatedMemoryEnabled()) {
  70             throw new RuntimeException(
  71                 "ThreadAllocatedMemory is expected to be disabled");
  72         }
  73 
  74         long sizes[] = mbean.getThreadAllocatedBytes(ids);
  75 
  76         if (sizes == null) {
  77           throw new RuntimeException("Null ThreadAllocatedBytes array returned");
  78         }
  79 
  80         for (int i = 0; i < NUM_THREADS; i++) {
  81             long s = sizes[i];
  82             if (s != -1) {
  83                 throw new RuntimeException(
  84                     "Invalid ThreadAllocatedBytes returned for thread " +
  85                     threads[i].getName() + " = " +  s + " expected = -1");
  86             }
  87         }
  88 
  89         // Enable allocated memory measurement
  90         if (!mbean.isThreadAllocatedMemoryEnabled()) {
  91             mbean.setThreadAllocatedMemoryEnabled(true);
  92         }
  93 
  94         if (!mbean.isThreadAllocatedMemoryEnabled()) {
  95             throw new RuntimeException(
  96                 "ThreadAllocatedMemory is expected to be enabled");
  97         }
  98 
  99         sizes = mbean.getThreadAllocatedBytes(ids);
 100 
 101         for (int i = 0; i < NUM_THREADS; i++) {
 102             long s = sizes[i];
 103             if (s < 0) {
 104                 throw new RuntimeException(
 105                     "Invalid allocated bytes returned for thread " +
 106                     threads[i].getName() + " = " + s);
 107             }
 108         }
 109 
 110         // let threads go and do some more allocation
 111         synchronized (obj) {
 112             done = true;
 113             obj.notifyAll();
 114         }
 115 
 116         // wait for threads to get going again.  we don't care if we
 117         // catch them in mid-execution or if some of them haven't
 118         // restarted after we're done sleeping.
 119         goSleep(400);
 120 
 121         long[] sizes1 = mbean.getThreadAllocatedBytes(ids);
 122 
 123         for (int i = 0; i < NUM_THREADS; i++) {
 124             long newSize = sizes1[i];
 125             if (sizes[i] > newSize) {
 126                 throw new RuntimeException("TEST FAILED: " +
 127                     threads[i].getName() +
 128                     " previous allocated bytes = " + sizes[i] +
 129                     " > current allocated bytes = " + newSize);
 130             }
 131             System.out.println(threads[i].getName() +
 132                 " Previous allocated bytes = " + sizes[i] +
 133                 " Current allocated bytes = " + newSize);
 134         }
 135 
 136         try {
 137             sizes = mbean.getThreadAllocatedBytes(null);
 138         } catch (NullPointerException e) {
 139             System.out.println(
 140                 "Caught expected NullPointerException: " + e.getMessage());
 141         }
 142 
 143         try {
 144             ids[0] = 0;
 145             sizes = mbean.getThreadAllocatedBytes(ids);
 146         } catch (IllegalArgumentException e) {
 147             System.out.println(
 148                 "Caught expected IllegalArgumentException: " + e.getMessage());
 149         }
 150 
 151 
 152         // let threads exit
 153         synchronized (obj) {
 154             done1 = true;
 155             obj.notifyAll();
 156         }
 157 
 158         for (int i = 0; i < NUM_THREADS; i++) {
 159             try {
 160                 threads[i].join();
 161             } catch (InterruptedException e) {
 162                 System.out.println("Unexpected exception is thrown.");
 163                 e.printStackTrace(System.out);
 164                 testFailed = true;
 165                 break;
 166             }
 167         }
 168 
 169         if (testFailed) {
 170             throw new RuntimeException("TEST FAILED");
 171         }
 172 
 173         System.out.println("Test passed");
 174     }
 175 
 176 
 177     private static void goSleep(long ms) throws Exception {
 178         try {
 179             Thread.sleep(ms);
 180         } catch (InterruptedException e) {
 181             System.out.println("Unexpected exception is thrown.");
 182             throw e;
 183         }
 184     }
 185 
 186     private static void waitUntilThreadBlocked()
 187         throws Exception {
 188         int count = 0;
 189         while (count != NUM_THREADS) {
 190             goSleep(100);
 191             count = 0;
 192             for (int i = 0; i < NUM_THREADS; i++) {
 193                 ThreadInfo info = mbean.getThreadInfo(threads[i].getId());
 194                 if (info.getThreadState() == Thread.State.WAITING) {
 195                     count++;
 196                 }
 197             }
 198         }
 199     }
 200 
 201     public static void doit() {
 202         String tmp = "";
 203         long hashCode = 0;
 204         for (int counter = 0; counter < 1000; counter++) {
 205             tmp += counter;
 206             hashCode = tmp.hashCode();
 207         }
 208         System.out.println(Thread.currentThread().getName() +
 209                            " hashcode: " + hashCode);
 210     }
 211 
 212     static class MyThread extends Thread {
 213         public MyThread(String name) {
 214             super(name);
 215         }
 216 
 217         public void run() {
 218             ThreadAllocatedMemoryArray.doit();
 219 
 220             synchronized (obj) {
 221                 while (!done) {
 222                     try {
 223                         obj.wait();
 224                     } catch (InterruptedException e) {
 225                         System.out.println("Unexpected exception is thrown.");
 226                         e.printStackTrace(System.out);
 227                         testFailed = true;
 228                         break;
 229                     }
 230                 }
 231             }
 232 
 233             ThreadAllocatedMemoryArray.doit();
 234 
 235             synchronized (obj) {
 236                 while (!done1) {
 237                     try {
 238                         obj.wait();
 239                     } catch (InterruptedException e) {
 240                         System.out.println("Unexpected exception is thrown.");
 241                         e.printStackTrace(System.out);
 242                         testFailed = true;
 243                         break;
 244                     }
 245                 }
 246             }
 247 
 248         }
 249     }
 250 }