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