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