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 37 import javax.management.openmbean.*; 38 import java.lang.management.LockInfo; 39 import java.lang.management.MonitorInfo; 40 import java.lang.management.ThreadInfo; 41 import java.util.Objects; 42 43 public 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 }