/* * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ /* * @test * @bug 4982289 * @summary Test ThreadInfo.from to return a valid * ThreadInfo object. Or throw exception if * the input CompositeData is invalid. * @author Mandy Chung * * @compile OpenTypeConverter.java * @build ThreadInfoCompositeData * @run main ThreadInfoCompositeData */ import javax.management.openmbean.*; import java.lang.management.LockInfo; import java.lang.management.MonitorInfo; import java.lang.management.ThreadInfo; import java.util.Objects; public class ThreadInfoCompositeData { private static StackTraceElement[] ste = new StackTraceElement[1]; private static CompositeData[] steCD = new CompositeData[1]; private static String lockClassName = "myClass"; private static int lockIdentityHashCode = 123456; private static String lockName = lockClassName + '@' + Integer.toHexString(lockIdentityHashCode); private static LockInfo lockInfo = new LockInfo(lockClassName, lockIdentityHashCode); public static void main(String[] argv) throws Exception { // A valid CompositeData is passed to ThreadInfo createGoodCompositeData(); // A valid CompositeData for JDK 5.0 ThreadInfo // is passed to ThreadInfo createV5ThreadInfo(); // An invalid CompositeData is passed to ThreadInfo.from() badNameCompositeData(); badTypeCompositeData(); System.out.println("Test passed"); } public static void createGoodCompositeData() throws Exception { CompositeType ct = new CompositeType("MyCompositeType", "CompositeType for ThreadInfo", validItemNames, validItemNames, validItemTypes); CompositeData cd = new CompositeDataSupport(ct, validItemNames, values); ThreadInfo info = ThreadInfo.from(cd); checkThreadInfo(info); } public static void createV5ThreadInfo() throws Exception { String[] v5ItemNames = new String[NUM_V5_ATTS]; OpenType[] v5ItemTypes = new OpenType[NUM_V5_ATTS]; Object[] v5ItemValues = new Object[NUM_V5_ATTS]; for (int i = 0; i < NUM_V5_ATTS; i++) { v5ItemNames[i] = validItemNames[i]; v5ItemTypes[i] = validItemTypes[i]; v5ItemValues[i] = values[i]; } CompositeType ct = new CompositeType("MyCompositeType", "CompositeType for JDK 5.0 ThreadInfo", v5ItemNames, v5ItemNames, v5ItemTypes); CompositeData cd = new CompositeDataSupport(ct, v5ItemNames, v5ItemValues); ThreadInfo info = ThreadInfo.from(cd); checkThreadInfo(info); } static void checkThreadInfo(ThreadInfo info) throws Exception { if (info.getThreadId() != ((Long) values[THREAD_ID]).longValue()) { throw new RuntimeException("Thread Id = " + info.getThreadId() + " expected = " + values[THREAD_ID]); } if (!info.getThreadName().equals(values[THREAD_NAME])) { throw new RuntimeException("Thread Name = " + info.getThreadName() + " expected = " + values[THREAD_NAME]); } if (info.getThreadState() != Thread.State.RUNNABLE) { throw new RuntimeException("Thread Name = " + info.getThreadName() + " expected = " + Thread.State.RUNNABLE); } if (info.getBlockedTime() != ((Long) values[BLOCKED_TIME]).longValue()) { throw new RuntimeException("blocked time = " + info.getBlockedTime() + " expected = " + values[BLOCKED_TIME]); } if (info.getBlockedCount() != ((Long) values[BLOCKED_COUNT]).longValue()) { throw new RuntimeException("blocked count = " + info.getBlockedCount() + " expected = " + values[BLOCKED_COUNT]); } if (info.getWaitedTime() != ((Long) values[WAITED_TIME]).longValue()) { throw new RuntimeException("waited time = " + info.getWaitedTime() + " expected = " + values[WAITED_TIME]); } if (info.getWaitedCount() != ((Long) values[WAITED_COUNT]).longValue()) { throw new RuntimeException("waited count = " + info.getWaitedCount() + " expected = " + values[WAITED_COUNT]); } if (!info.getLockName().equals(values[LOCK_NAME])) { throw new RuntimeException("Lock Name = " + info.getLockName() + " expected = " + values[LOCK_NAME]); } if (info.getLockOwnerId() != ((Long) values[LOCK_OWNER_ID]).longValue()) { throw new RuntimeException( "LockOwner Id = " + info.getLockOwnerId() + " expected = " + values[LOCK_OWNER_ID]); } if (!info.getLockOwnerName().equals(values[LOCK_OWNER_NAME])) { throw new RuntimeException("LockOwner Name = " + info.getLockOwnerName() + " expected = " + values[LOCK_OWNER_NAME]); } if (!values[DAEMON].equals(info.isDaemon())) { throw new RuntimeException("Daemon = " + info.isDaemon() + " expected = " + values[DAEMON]); } checkStackTrace(info.getStackTrace()); checkLockInfo(info.getLockInfo()); } private static void checkStackTrace(StackTraceElement[] s) throws Exception { if (ste.length != s.length) { throw new RuntimeException("Stack Trace length = " + s.length + " expected = " + ste.length); } StackTraceElement s1 = ste[0]; StackTraceElement s2 = s[0]; if (!s1.getClassName().equals(s2.getClassName())) { throw new RuntimeException("Class name = " + s2.getClassName() + " expected = " + s1.getClassName()); } if (!Objects.equals(s1.getModuleName(), s2.getModuleName())) { throw new RuntimeException("Module name = " + s2.getModuleName() + " expected = " + s1.getModuleName()); } if (!Objects.equals(s1.getModuleVersion(), s2.getModuleVersion())) { throw new RuntimeException("Module version = " + s2.getModuleVersion() + " expected = " + s1.getModuleVersion()); } if (!s1.getMethodName().equals(s2.getMethodName())) { throw new RuntimeException("Method name = " + s2.getMethodName() + " expected = " + s1.getMethodName()); } if (!s1.getFileName().equals(s2.getFileName())) { throw new RuntimeException("File name = " + s2.getFileName() + " expected = " + s1.getFileName()); } if (s1.getLineNumber() != s2.getLineNumber()) { throw new RuntimeException("Line number = " + s2.getLineNumber() + " expected = " + s1.getLineNumber()); } } private static void checkLockInfo(LockInfo li) throws Exception { if (!li.getClassName().equals(lockInfo.getClassName())) { throw new RuntimeException("Class Name = " + li.getClassName() + " expected = " + lockInfo.getClassName()); } if (li.getIdentityHashCode() != lockInfo.getIdentityHashCode()) { throw new RuntimeException("Class Name = " + li.getIdentityHashCode() + " expected = " + lockInfo.getIdentityHashCode()); } } public static void badNameCompositeData() throws Exception { CompositeType ct = new CompositeType("MyCompositeType", "CompositeType for ThreadInfo", badItemNames, badItemNames, validItemTypes); CompositeData cd = new CompositeDataSupport(ct, badItemNames, values); try { ThreadInfo info = ThreadInfo.from(cd); } catch (IllegalArgumentException e) { System.out.println("Expected exception: " + e.getMessage()); return; } throw new RuntimeException( "IllegalArgumentException not thrown"); } public static void badTypeCompositeData() throws Exception { CompositeType ct = new CompositeType("MyCompositeType", "CompositeType for ThreadInfo", validItemNames, validItemNames, badItemTypes); // patch values[STACK_TRACE] to Long values[STACK_TRACE] = new Long(1000); values[LOCK_INFO] = new Long(1000); CompositeData cd = new CompositeDataSupport(ct, validItemNames, values); try { ThreadInfo info = ThreadInfo.from(cd); } catch (IllegalArgumentException e) { System.out.println("Expected exception: " + e.getMessage()); return; } throw new RuntimeException( "IllegalArgumentException not thrown"); } private static final int THREAD_ID = 0; private static final int THREAD_NAME = 1; private static final int THREAD_STATE = 2; private static final int BLOCKED_TIME = 3; private static final int BLOCKED_COUNT = 4; private static final int WAITED_TIME = 5; private static final int WAITED_COUNT = 6; private static final int LOCK_NAME = 7; private static final int LOCK_OWNER_ID = 8; private static final int LOCK_OWNER_NAME = 9; private static final int STACK_TRACE = 10; private static final int SUSPENDED = 11; private static final int IN_NATIVE = 12; private static final int NUM_V5_ATTS = 13; // JDK 6.0 ThreadInfo attributes private static final int LOCK_INFO = 13; // JDK 9.0 ThreadInfo attributes private static final int DAEMON = 14; private static final int PRIORITY = 15; private static final String[] validItemNames = { "threadId", "threadName", "threadState", "blockedTime", "blockedCount", "waitedTime", "waitedCount", "lockName", "lockOwnerId", "lockOwnerName", "stackTrace", "suspended", "inNative", "lockInfo", "daemon", "priority", }; private static OpenType[] validItemTypes = { SimpleType.LONG, SimpleType.STRING, SimpleType.STRING, SimpleType.LONG, SimpleType.LONG, SimpleType.LONG, SimpleType.LONG, SimpleType.STRING, SimpleType.LONG, SimpleType.STRING, null, // ArrayType for StackTraceElement[] SimpleType.BOOLEAN, SimpleType.BOOLEAN, null, // CompositeType for LockInfo SimpleType.BOOLEAN, SimpleType.INTEGER, }; private static Object[] values = { new Long(100), "FooThread", "RUNNABLE", new Long(200), new Long(10), new Long(300), new Long(20), lockName, new Long(99), "BarThread", steCD, new Boolean(false), new Boolean(false), null, // To be initialized to lockInfoCD new Boolean(false), Thread.NORM_PRIORITY, }; private static final String[] steItemNames = { "classLoaderName", "moduleName", "moduleVersion", "className", "methodName", "fileName", "lineNumber", "nativeMethod", }; private static final String[] lockInfoItemNames = { "className", "identityHashCode", }; static { // create stack trace element ste[0] = new StackTraceElement("FooClass", "getFoo", "Foo.java", 100); // initialize the ste[0] and values and validItemTypes try { CompositeType steCType = (CompositeType) OpenTypeConverter.toOpenType(StackTraceElement.class); validItemTypes[STACK_TRACE] = new ArrayType(1, steCType); final Object[] steValue = { ste[0].getClassLoaderName(), ste[0].getModuleName(), ste[0].getModuleVersion(), ste[0].getClassName(), ste[0].getMethodName(), ste[0].getFileName(), new Integer(ste[0].getLineNumber()), new Boolean(ste[0].isNativeMethod()), }; steCD[0] = new CompositeDataSupport(steCType, steItemNames, steValue); CompositeType lockInfoCType = (CompositeType) OpenTypeConverter.toOpenType(LockInfo.class); validItemTypes[LOCK_INFO] = lockInfoCType; final Object[] lockInfoValue = { lockInfo.getClassName(), lockInfo.getIdentityHashCode(), }; values[LOCK_INFO] = new CompositeDataSupport(lockInfoCType, lockInfoItemNames, lockInfoValue); } catch (Exception e) { throw new RuntimeException(e); } } private static final String[] badItemNames = { "threadId", "threadName", "threadState", "blockedTime", "blockedCount", "waitedTime", "waitedCount", "lockName", "lockOwnerId", "lockOwnerName", "BadStackTrace", // bad item name "suspended", "inNative", "lockInfo", "daemon", "priority", }; private static final OpenType[] badItemTypes = { SimpleType.LONG, SimpleType.STRING, SimpleType.STRING, SimpleType.LONG, SimpleType.LONG, SimpleType.LONG, SimpleType.LONG, SimpleType.STRING, SimpleType.LONG, SimpleType.STRING, SimpleType.LONG, // bad type SimpleType.BOOLEAN, SimpleType.BOOLEAN, SimpleType.LONG, // bad type SimpleType.BOOLEAN, SimpleType.INTEGER, }; }