21 * questions. |
21 * questions. |
22 */ |
22 */ |
23 |
23 |
24 /* |
24 /* |
25 * @test |
25 * @test |
26 * @bug 6173675 |
26 * @bug 6173675 8231209 |
27 * @summary Basic test of ThreadMXBean.getThreadAllocatedBytes |
27 * @summary Basic test of ThreadMXBean.getThreadAllocatedBytes |
28 * @author Paul Hohensee |
28 * @author Paul Hohensee |
29 */ |
29 */ |
30 |
30 |
31 import java.lang.management.*; |
31 import java.lang.management.*; |
32 |
32 |
33 public class ThreadAllocatedMemory { |
33 public class ThreadAllocatedMemory { |
34 private static com.sun.management.ThreadMXBean mbean = |
34 private static com.sun.management.ThreadMXBean mbean = |
35 (com.sun.management.ThreadMXBean)ManagementFactory.getThreadMXBean(); |
35 (com.sun.management.ThreadMXBean)ManagementFactory.getThreadMXBean(); |
36 private static boolean testFailed = false; |
36 private static volatile boolean done = false; |
37 private static boolean done = false; |
37 private static volatile boolean done1 = false; |
38 private static boolean done1 = false; |
|
39 private static Object obj = new Object(); |
38 private static Object obj = new Object(); |
40 private static final int NUM_THREADS = 10; |
39 private static final int NUM_THREADS = 10; |
41 private static Thread[] threads = new Thread[NUM_THREADS]; |
40 private static Thread[] threads = new Thread[NUM_THREADS]; |
42 private static long[] sizes = new long[NUM_THREADS]; |
41 private static long[] sizes = new long[NUM_THREADS]; |
43 |
42 |
44 public static void main(String[] argv) |
43 public static void main(String[] argv) |
45 throws Exception { |
44 throws Exception { |
46 |
45 |
|
46 testSupportEnableDisable(); |
|
47 |
|
48 // Test current thread two ways |
|
49 testGetCurrentThreadAllocatedBytes(); |
|
50 testCurrentThreadGetThreadAllocatedBytes(); |
|
51 |
|
52 // Test a single thread that is not this one |
|
53 testGetThreadAllocatedBytes(); |
|
54 |
|
55 // Test many threads that are not this one |
|
56 testGetThreadsAllocatedBytes(); |
|
57 |
|
58 System.out.println("Test passed"); |
|
59 } |
|
60 |
|
61 private static void testSupportEnableDisable() { |
47 if (!mbean.isThreadAllocatedMemorySupported()) { |
62 if (!mbean.isThreadAllocatedMemorySupported()) { |
48 return; |
63 return; |
49 } |
64 } |
50 |
65 |
51 // disable allocated memory measurement |
66 // disable allocated memory measurement |
75 |
87 |
76 if (!mbean.isThreadAllocatedMemoryEnabled()) { |
88 if (!mbean.isThreadAllocatedMemoryEnabled()) { |
77 throw new RuntimeException( |
89 throw new RuntimeException( |
78 "ThreadAllocatedMemory is expected to be enabled"); |
90 "ThreadAllocatedMemory is expected to be enabled"); |
79 } |
91 } |
|
92 } |
|
93 |
|
94 private static void testGetCurrentThreadAllocatedBytes() { |
|
95 long size = mbean.getCurrentThreadAllocatedBytes(); |
|
96 ensureValidSize(size); |
|
97 |
|
98 // do some more allocation |
|
99 doit(); |
|
100 |
|
101 checkResult(Thread.currentThread(), size, |
|
102 mbean.getCurrentThreadAllocatedBytes()); |
|
103 } |
|
104 |
|
105 private static void testCurrentThreadGetThreadAllocatedBytes() { |
|
106 Thread curThread = Thread.currentThread(); |
|
107 long id = curThread.getId(); |
80 |
108 |
81 long size = mbean.getThreadAllocatedBytes(id); |
109 long size = mbean.getThreadAllocatedBytes(id); |
82 // implementation could have started measurement when |
110 ensureValidSize(size); |
83 // measurement was enabled, in which case size can be 0 |
111 |
84 if (size < 0) { |
112 // do some more allocation |
85 throw new RuntimeException( |
|
86 "Invalid allocated bytes returned = " + size); |
|
87 } |
|
88 |
|
89 doit(); |
113 doit(); |
90 |
114 |
91 // Expected to be size1 >= size |
115 checkResult(curThread, size, mbean.getThreadAllocatedBytes(id)); |
92 long size1 = mbean.getThreadAllocatedBytes(id); |
116 } |
93 if (size1 < size) { |
117 |
94 throw new RuntimeException("Allocated bytes " + size1 + |
118 private static void testGetThreadAllocatedBytes() |
95 " expected >= " + size); |
119 throws Exception { |
96 } |
120 |
97 System.out.println(curThread.getName() + |
121 // start a thread |
98 " Current thread allocated bytes = " + size + |
122 done = false; done1 = false; |
99 " allocated bytes = " + size1); |
123 Thread curThread = new MyThread("MyThread"); |
100 |
124 curThread.start(); |
101 |
125 long id = curThread.getId(); |
102 // start threads, wait for them to block |
126 |
|
127 // wait for thread to block after doing some allocation |
|
128 waitUntilThreadBlocked(curThread); |
|
129 |
|
130 long size = mbean.getThreadAllocatedBytes(id); |
|
131 ensureValidSize(size); |
|
132 |
|
133 // let thread go to do some more allocation |
|
134 synchronized (obj) { |
|
135 done = true; |
|
136 obj.notifyAll(); |
|
137 } |
|
138 |
|
139 // wait for thread to get going again. we don't care if we |
|
140 // catch it in mid-execution or if it hasn't |
|
141 // restarted after we're done sleeping. |
|
142 goSleep(400); |
|
143 |
|
144 checkResult(curThread, size, mbean.getThreadAllocatedBytes(id)); |
|
145 |
|
146 // let thread exit |
|
147 synchronized (obj) { |
|
148 done1 = true; |
|
149 obj.notifyAll(); |
|
150 } |
|
151 |
|
152 try { |
|
153 curThread.join(); |
|
154 } catch (InterruptedException e) { |
|
155 System.out.println("Unexpected exception is thrown."); |
|
156 e.printStackTrace(System.out); |
|
157 } |
|
158 } |
|
159 |
|
160 private static void testGetThreadsAllocatedBytes() |
|
161 throws Exception { |
|
162 |
|
163 // start threads |
|
164 done = false; done1 = false; |
103 for (int i = 0; i < NUM_THREADS; i++) { |
165 for (int i = 0; i < NUM_THREADS; i++) { |
104 threads[i] = new MyThread("MyThread-" + i); |
166 threads[i] = new MyThread("MyThread-" + i); |
105 threads[i].start(); |
167 threads[i].start(); |
106 } |
168 } |
107 |
169 |
108 // threads block after doing some allocation |
170 // wait for threads to block after doing some allocation |
109 waitUntilThreadBlocked(); |
171 waitUntilThreadsBlocked(); |
110 |
172 |
111 for (int i = 0; i < NUM_THREADS; i++) { |
173 for (int i = 0; i < NUM_THREADS; i++) { |
112 sizes[i] = mbean.getThreadAllocatedBytes(threads[i].getId()); |
174 sizes[i] = mbean.getThreadAllocatedBytes(threads[i].getId()); |
113 } |
175 ensureValidSize(sizes[i]); |
114 |
176 } |
115 // let threads go and do some more allocation |
177 |
|
178 // let threads go to do some more allocation |
116 synchronized (obj) { |
179 synchronized (obj) { |
117 done = true; |
180 done = true; |
118 obj.notifyAll(); |
181 obj.notifyAll(); |
119 } |
182 } |
120 |
183 |
121 // wait for threads to get going again. we don't care if we |
184 // wait for threads to get going again. we don't care if we |
122 // catch them in mid-execution or if some of them haven't |
185 // catch them in mid-execution or if some of them haven't |
123 // restarted after we're done sleeping. |
186 // restarted after we're done sleeping. |
124 goSleep(400); |
187 goSleep(400); |
125 |
188 |
126 for (int i = 0; i < NUM_THREADS; i++) { |
189 for (int i = 0; i < NUM_THREADS; i++) { |
127 long newSize = mbean.getThreadAllocatedBytes(threads[i].getId()); |
190 checkResult(threads[i], sizes[i], |
128 if (sizes[i] > newSize) { |
191 mbean.getThreadAllocatedBytes(threads[i].getId())); |
129 throw new RuntimeException("TEST FAILED: " + |
|
130 threads[i].getName() + |
|
131 " previous allocated bytes = " + sizes[i] + |
|
132 " > current allocated bytes = " + newSize); |
|
133 } |
|
134 System.out.println(threads[i].getName() + |
|
135 " Previous allocated bytes = " + sizes[i] + |
|
136 " Current allocated bytes = " + newSize); |
|
137 } |
192 } |
138 |
193 |
139 // let threads exit |
194 // let threads exit |
140 synchronized (obj) { |
195 synchronized (obj) { |
141 done1 = true; |
196 done1 = true; |
146 try { |
201 try { |
147 threads[i].join(); |
202 threads[i].join(); |
148 } catch (InterruptedException e) { |
203 } catch (InterruptedException e) { |
149 System.out.println("Unexpected exception is thrown."); |
204 System.out.println("Unexpected exception is thrown."); |
150 e.printStackTrace(System.out); |
205 e.printStackTrace(System.out); |
151 testFailed = true; |
|
152 break; |
206 break; |
153 } |
207 } |
154 } |
208 } |
155 if (testFailed) { |
209 } |
156 throw new RuntimeException("TEST FAILED"); |
210 |
157 } |
211 private static void ensureValidSize(long size) { |
158 |
212 // implementation could have started measurement when |
159 System.out.println("Test passed"); |
213 // measurement was enabled, in which case size can be 0 |
160 } |
214 if (size < 0) { |
161 |
215 throw new RuntimeException( |
|
216 "Invalid allocated bytes returned = " + size); |
|
217 } |
|
218 } |
|
219 |
|
220 private static void checkResult(Thread curThread, |
|
221 long prev_size, long curr_size) { |
|
222 if (curr_size < prev_size) { |
|
223 throw new RuntimeException("Allocated bytes " + curr_size + |
|
224 " expected >= " + prev_size); |
|
225 } |
|
226 System.out.println(curThread.getName() + |
|
227 " Previous allocated bytes = " + prev_size + |
|
228 " Current allocated bytes = " + curr_size); |
|
229 } |
162 |
230 |
163 private static void goSleep(long ms) throws Exception { |
231 private static void goSleep(long ms) throws Exception { |
164 try { |
232 try { |
165 Thread.sleep(ms); |
233 Thread.sleep(ms); |
166 } catch (InterruptedException e) { |
234 } catch (InterruptedException e) { |
167 System.out.println("Unexpected exception is thrown."); |
235 System.out.println("Unexpected exception is thrown."); |
168 throw e; |
236 throw e; |
169 } |
237 } |
170 } |
238 } |
171 |
239 |
172 private static void waitUntilThreadBlocked() |
240 private static void waitUntilThreadBlocked(Thread thread) |
|
241 throws Exception { |
|
242 while (true) { |
|
243 goSleep(100); |
|
244 ThreadInfo info = mbean.getThreadInfo(thread.getId()); |
|
245 if (info.getThreadState() == Thread.State.WAITING) { |
|
246 break; |
|
247 } |
|
248 } |
|
249 } |
|
250 |
|
251 private static void waitUntilThreadsBlocked() |
173 throws Exception { |
252 throws Exception { |
174 int count = 0; |
253 int count = 0; |
175 while (count != NUM_THREADS) { |
254 while (count != NUM_THREADS) { |
176 goSleep(100); |
255 goSleep(100); |
177 count = 0; |
256 count = 0; |