ThreadInfoCompositeData.java revision 16930:13c06d444258
1/*
2 * Copyright (c) 2004, 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     4982289
27 * @summary Test ThreadInfo.from to return a valid
28 *          ThreadInfo object. Or throw exception if
29 *          the input CompositeData is invalid.
30 * @author  Mandy Chung
31 *
32 * @compile OpenTypeConverter.java
33 * @build ThreadInfoCompositeData
34 * @run main ThreadInfoCompositeData
35 */
36
37import javax.management.openmbean.*;
38import java.lang.management.LockInfo;
39import java.lang.management.MonitorInfo;
40import java.lang.management.ThreadInfo;
41import java.util.Objects;
42
43public class ThreadInfoCompositeData {
44    private static StackTraceElement[] ste = new StackTraceElement[1];
45    private static CompositeData[] steCD = new CompositeData[1];
46    private static String lockClassName = "myClass";
47    private static int lockIdentityHashCode = 123456;
48    private static String lockName = lockClassName + '@' +
49        Integer.toHexString(lockIdentityHashCode);
50    private static LockInfo lockInfo =
51        new LockInfo(lockClassName, lockIdentityHashCode);
52
53    public static void main(String[] argv) throws Exception {
54        // A valid CompositeData is passed to ThreadInfo
55        createGoodCompositeData();
56        // A valid CompositeData for JDK 5.0 ThreadInfo
57        // is passed to ThreadInfo
58        createV5ThreadInfo();
59        // An invalid CompositeData is passed to ThreadInfo.from()
60        badNameCompositeData();
61        badTypeCompositeData();
62        System.out.println("Test passed");
63    }
64
65    public static void createGoodCompositeData() throws Exception {
66        CompositeType ct =
67            new CompositeType("MyCompositeType",
68                              "CompositeType for ThreadInfo",
69                              validItemNames,
70                              validItemNames,
71                              validItemTypes);
72        CompositeData cd =
73            new CompositeDataSupport(ct,
74                                     validItemNames,
75                                     values);
76        ThreadInfo info = ThreadInfo.from(cd);
77        checkThreadInfo(info);
78   }
79
80    public static void createV5ThreadInfo() throws Exception {
81        String[] v5ItemNames = new String[NUM_V5_ATTS];
82        OpenType[] v5ItemTypes = new OpenType[NUM_V5_ATTS];
83        Object[] v5ItemValues = new Object[NUM_V5_ATTS];
84        for (int i = 0; i < NUM_V5_ATTS; i++) {
85            v5ItemNames[i] = validItemNames[i];
86            v5ItemTypes[i] = validItemTypes[i];
87            v5ItemValues[i] = values[i];
88        }
89        CompositeType ct =
90            new CompositeType("MyCompositeType",
91                              "CompositeType for JDK 5.0 ThreadInfo",
92                              v5ItemNames,
93                              v5ItemNames,
94                              v5ItemTypes);
95        CompositeData cd =
96            new CompositeDataSupport(ct,
97                                     v5ItemNames,
98                                     v5ItemValues);
99        ThreadInfo info = ThreadInfo.from(cd);
100        checkThreadInfo(info);
101   }
102
103   static void checkThreadInfo(ThreadInfo info) throws Exception {
104        if (info.getThreadId() != ((Long) values[THREAD_ID]).longValue()) {
105            throw new RuntimeException("Thread Id = " + info.getThreadId() +
106               " expected = " + values[THREAD_ID]);
107        }
108        if (!info.getThreadName().equals(values[THREAD_NAME])) {
109            throw new RuntimeException("Thread Name = " +
110               info.getThreadName() + " expected = " + values[THREAD_NAME]);
111        }
112        if (info.getThreadState() != Thread.State.RUNNABLE) {
113            throw new RuntimeException("Thread Name = " +
114               info.getThreadName() + " expected = " + Thread.State.RUNNABLE);
115        }
116        if (info.getBlockedTime() != ((Long) values[BLOCKED_TIME]).longValue()) {
117            throw new RuntimeException("blocked time = " +
118               info.getBlockedTime() +
119               " expected = " + values[BLOCKED_TIME]);
120        }
121        if (info.getBlockedCount() != ((Long) values[BLOCKED_COUNT]).longValue()) {
122            throw new RuntimeException("blocked count = " +
123               info.getBlockedCount() +
124               " expected = " + values[BLOCKED_COUNT]);
125        }
126        if (info.getWaitedTime() != ((Long) values[WAITED_TIME]).longValue()) {
127            throw new RuntimeException("waited time = " +
128               info.getWaitedTime() +
129               " expected = " + values[WAITED_TIME]);
130        }
131        if (info.getWaitedCount() != ((Long) values[WAITED_COUNT]).longValue()) {
132            throw new RuntimeException("waited count = " +
133               info.getWaitedCount() +
134               " expected = " + values[WAITED_COUNT]);
135        }
136        if (!info.getLockName().equals(values[LOCK_NAME])) {
137            throw new RuntimeException("Lock Name = " +
138               info.getLockName() + " expected = " + values[LOCK_NAME]);
139        }
140        if (info.getLockOwnerId() !=
141                ((Long) values[LOCK_OWNER_ID]).longValue()) {
142            throw new RuntimeException(
143               "LockOwner Id = " + info.getLockOwnerId() +
144               " expected = " + values[LOCK_OWNER_ID]);
145        }
146        if (!info.getLockOwnerName().equals(values[LOCK_OWNER_NAME])) {
147            throw new RuntimeException("LockOwner Name = " +
148               info.getLockOwnerName() + " expected = " +
149               values[LOCK_OWNER_NAME]);
150        }
151        if (!values[DAEMON].equals(info.isDaemon())) {
152            throw new RuntimeException("Daemon = " +
153               info.isDaemon() + " expected = " +
154               values[DAEMON]);
155        }
156
157        checkStackTrace(info.getStackTrace());
158
159        checkLockInfo(info.getLockInfo());
160    }
161
162    private static void checkStackTrace(StackTraceElement[] s)
163        throws Exception {
164        if (ste.length != s.length) {
165            throw new RuntimeException("Stack Trace length = " +
166                s.length + " expected = " + ste.length);
167        }
168
169        StackTraceElement s1 = ste[0];
170        StackTraceElement s2 = s[0];
171
172        if (!s1.getClassName().equals(s2.getClassName())) {
173            throw new RuntimeException("Class name = " +
174                s2.getClassName() + " expected = " + s1.getClassName());
175        }
176        if (!Objects.equals(s1.getModuleName(), s2.getModuleName())) {
177            throw new RuntimeException("Module name = " +
178                s2.getModuleName() + " expected = " + s1.getModuleName());
179        }
180        if (!Objects.equals(s1.getModuleVersion(), s2.getModuleVersion())) {
181            throw new RuntimeException("Module version = " +
182                s2.getModuleVersion() + " expected = " + s1.getModuleVersion());
183        }
184        if (!s1.getMethodName().equals(s2.getMethodName())) {
185            throw new RuntimeException("Method name = " +
186                s2.getMethodName() + " expected = " + s1.getMethodName());
187        }
188        if (!s1.getFileName().equals(s2.getFileName())) {
189            throw new RuntimeException("File name = " +
190                s2.getFileName() + " expected = " + s1.getFileName());
191        }
192        if (s1.getLineNumber() != s2.getLineNumber()) {
193            throw new RuntimeException("Line number = " +
194                s2.getLineNumber() + " expected = " + s1.getLineNumber());
195        }
196    }
197
198    private static void checkLockInfo(LockInfo li)
199        throws Exception {
200        if (!li.getClassName().equals(lockInfo.getClassName())) {
201            throw new RuntimeException("Class Name = " +
202                li.getClassName() + " expected = " + lockInfo.getClassName());
203        }
204        if (li.getIdentityHashCode() != lockInfo.getIdentityHashCode()) {
205            throw new RuntimeException("Class Name = " +
206                li.getIdentityHashCode() + " expected = " +
207                lockInfo.getIdentityHashCode());
208        }
209    }
210
211    public static void badNameCompositeData() throws Exception {
212        CompositeType ct =
213            new CompositeType("MyCompositeType",
214                              "CompositeType for ThreadInfo",
215                              badItemNames,
216                              badItemNames,
217                              validItemTypes);
218        CompositeData cd =
219            new CompositeDataSupport(ct,
220                                     badItemNames,
221                                     values);
222
223        try {
224            ThreadInfo info = ThreadInfo.from(cd);
225        } catch (IllegalArgumentException e) {
226            System.out.println("Expected exception: " +
227                e.getMessage());
228            return;
229        }
230        throw new RuntimeException(
231            "IllegalArgumentException not thrown");
232    }
233
234    public static void badTypeCompositeData() throws Exception {
235        CompositeType ct =
236            new CompositeType("MyCompositeType",
237                              "CompositeType for ThreadInfo",
238                              validItemNames,
239                              validItemNames,
240                              badItemTypes);
241
242        // patch values[STACK_TRACE] to Long
243        values[STACK_TRACE] = new Long(1000);
244        values[LOCK_INFO] = new Long(1000);
245        CompositeData cd =
246            new CompositeDataSupport(ct,
247                                     validItemNames,
248                                     values);
249
250        try {
251            ThreadInfo info = ThreadInfo.from(cd);
252        } catch (IllegalArgumentException e) {
253            System.out.println("Expected exception: " +
254                e.getMessage());
255            return;
256        }
257        throw new RuntimeException(
258            "IllegalArgumentException not thrown");
259    }
260
261    private static final int THREAD_ID       = 0;
262    private static final int THREAD_NAME     = 1;
263    private static final int THREAD_STATE    = 2;
264    private static final int BLOCKED_TIME    = 3;
265    private static final int BLOCKED_COUNT   = 4;
266    private static final int WAITED_TIME     = 5;
267    private static final int WAITED_COUNT    = 6;
268    private static final int LOCK_NAME       = 7;
269    private static final int LOCK_OWNER_ID   = 8;
270    private static final int LOCK_OWNER_NAME = 9;
271    private static final int STACK_TRACE     = 10;
272    private static final int SUSPENDED       = 11;
273    private static final int IN_NATIVE       = 12;
274    private static final int NUM_V5_ATTS     = 13;
275    // JDK 6.0 ThreadInfo attributes
276    private static final int LOCK_INFO       = 13;
277    // JDK 9.0 ThreadInfo attributes
278    private static final int DAEMON          = 14;
279    private static final int PRIORITY        = 15;
280
281    private static final String[] validItemNames = {
282        "threadId",
283        "threadName",
284        "threadState",
285        "blockedTime",
286        "blockedCount",
287        "waitedTime",
288        "waitedCount",
289        "lockName",
290        "lockOwnerId",
291        "lockOwnerName",
292        "stackTrace",
293        "suspended",
294        "inNative",
295        "lockInfo",
296        "daemon",
297        "priority",
298    };
299
300    private static OpenType[] validItemTypes = {
301        SimpleType.LONG,
302        SimpleType.STRING,
303        SimpleType.STRING,
304        SimpleType.LONG,
305        SimpleType.LONG,
306        SimpleType.LONG,
307        SimpleType.LONG,
308        SimpleType.STRING,
309        SimpleType.LONG,
310        SimpleType.STRING,
311        null,  // ArrayType for StackTraceElement[]
312        SimpleType.BOOLEAN,
313        SimpleType.BOOLEAN,
314        null,  // CompositeType for LockInfo
315        SimpleType.BOOLEAN,
316        SimpleType.INTEGER,
317    };
318
319    private static Object[] values = {
320        new Long(100),
321        "FooThread",
322        "RUNNABLE",
323        new Long(200),
324        new Long(10),
325        new Long(300),
326        new Long(20),
327        lockName,
328        new Long(99),
329        "BarThread",
330        steCD,
331        new Boolean(false),
332        new Boolean(false),
333        null, // To be initialized to lockInfoCD
334        new Boolean(false),
335        Thread.NORM_PRIORITY,
336    };
337
338    private static final String[] steItemNames = {
339        "classLoaderName",
340        "moduleName",
341        "moduleVersion",
342        "className",
343        "methodName",
344        "fileName",
345        "lineNumber",
346        "nativeMethod",
347    };
348
349    private static final String[] lockInfoItemNames = {
350        "className",
351        "identityHashCode",
352    };
353
354    static {
355        // create stack trace element
356        ste[0] = new StackTraceElement("FooClass", "getFoo", "Foo.java", 100);
357
358        // initialize the ste[0] and values and validItemTypes
359        try {
360            CompositeType steCType = (CompositeType)
361                OpenTypeConverter.toOpenType(StackTraceElement.class);
362            validItemTypes[STACK_TRACE] = new ArrayType(1, steCType);
363
364            final Object[] steValue = {
365                ste[0].getClassLoaderName(),
366                ste[0].getModuleName(),
367                ste[0].getModuleVersion(),
368                ste[0].getClassName(),
369                ste[0].getMethodName(),
370                ste[0].getFileName(),
371                new Integer(ste[0].getLineNumber()),
372                new Boolean(ste[0].isNativeMethod()),
373            };
374
375            steCD[0] =
376                new CompositeDataSupport(steCType,
377                                         steItemNames,
378                                         steValue);
379
380            CompositeType lockInfoCType = (CompositeType)
381                OpenTypeConverter.toOpenType(LockInfo.class);
382            validItemTypes[LOCK_INFO] = lockInfoCType;
383
384            final Object[] lockInfoValue = {
385                lockInfo.getClassName(),
386                lockInfo.getIdentityHashCode(),
387            };
388
389            values[LOCK_INFO] =
390                new CompositeDataSupport(lockInfoCType,
391                                         lockInfoItemNames,
392                                         lockInfoValue);
393        } catch (Exception e) {
394            throw new RuntimeException(e);
395        }
396    }
397
398    private static final String[] badItemNames = {
399        "threadId",
400        "threadName",
401        "threadState",
402        "blockedTime",
403        "blockedCount",
404        "waitedTime",
405        "waitedCount",
406        "lockName",
407        "lockOwnerId",
408        "lockOwnerName",
409        "BadStackTrace", // bad item name
410        "suspended",
411        "inNative",
412        "lockInfo",
413        "daemon",
414        "priority",
415    };
416    private static final OpenType[] badItemTypes = {
417        SimpleType.LONG,
418        SimpleType.STRING,
419        SimpleType.STRING,
420        SimpleType.LONG,
421        SimpleType.LONG,
422        SimpleType.LONG,
423        SimpleType.LONG,
424        SimpleType.STRING,
425        SimpleType.LONG,
426        SimpleType.STRING,
427        SimpleType.LONG,  // bad type
428        SimpleType.BOOLEAN,
429        SimpleType.BOOLEAN,
430        SimpleType.LONG,  // bad type
431        SimpleType.BOOLEAN,
432        SimpleType.INTEGER,
433    };
434
435}
436