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