1 /* 2 * Copyright (c) 2004, 2018, 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 8198253 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/sun.management 33 * @build ThreadInfoCompositeData OpenTypeConverter 34 * @run testng/othervm ThreadInfoCompositeData 35 */ 36 37 38 import javax.management.openmbean.*; 39 import java.lang.management.LockInfo; 40 import java.lang.management.MonitorInfo; 41 import java.lang.management.ThreadInfo; 42 import java.util.Arrays; 43 import java.util.Objects; 44 import java.util.stream.Stream; 45 46 import org.testng.annotations.Test; 47 import static org.testng.Assert.*; 48 49 public class ThreadInfoCompositeData { 50 private static String lockClassName = "myClass"; 51 private static int lockIdentityHashCode = 123456; 52 private static String lockName = lockClassName + '@' + 53 Integer.toHexString(lockIdentityHashCode); 54 private static LockInfo lockInfo = 55 new LockInfo(lockClassName, lockIdentityHashCode); 56 57 @Test 58 public static void createGoodCompositeData() throws Exception { 59 CompositeData cd = Factory.makeThreadInfoCompositeData(); 60 ThreadInfo info = ThreadInfo.from(cd); 61 checkThreadInfo(info); 62 } 63 64 /* 65 * An invalid CompositeData with JDK 9 attributes but missing JDK 6 attributes 66 */ 67 @Test 68 public static void badMissingCompositeData() throws Exception { 69 CompositeData cd = Factory.makeCompositeDataMissingV6(); 70 try { 71 ThreadInfo info = ThreadInfo.from(cd); 72 throw new RuntimeException("IllegalArgumentException not thrown"); 73 } catch (IllegalArgumentException e) {} 74 } 75 76 static final StackTraceElement STE = 77 new StackTraceElement("FooClass", "getFoo", "Foo.java", 100); 78 79 80 /* 81 * Current version of ThreadInfo but an older version of StackTraceElement 82 */ 83 @Test 84 public static void withV5StackTraceCompositeData() throws Exception { 85 CompositeData cd = Factory.makeThreadInfoWithV5StackTrace(); 86 try { 87 ThreadInfo info = ThreadInfo.from(cd); 88 throw new RuntimeException("IllegalArgumentException not thrown"); 89 } catch (IllegalArgumentException e) {} 90 } 91 92 /* 93 * Current version of ThreadInfo but an older version of MonitorInfo 94 * and the value of "lockedStackFrame" attribute is null. 95 */ 96 @Test 97 public static void withInvalidMonitorInfoCompositeData() throws Exception { 98 CompositeData cd = Factory.makeThreadInfoWithIncompatibleMonitorInfo(); 99 100 // verify MonitorInfo is valid 101 CompositeData[] monitors = (CompositeData[])cd.get("lockedMonitors"); 102 CompositeData ste = (CompositeData)monitors[0].get("lockedStackFrame"); 103 if (((Integer)monitors[0].get("lockedStackDepth")) >= 0 || ste != null) { 104 throw new RuntimeException("Expected negative stack depth and null stack frame"); 105 } 106 MonitorInfo minfo = MonitorInfo.from(monitors[0]); 107 checkLockInfo(minfo); 108 if (minfo.getLockedStackFrame() != null) { 109 throw new RuntimeException("Expected null stack frame"); 110 } 111 112 try { 113 ThreadInfo info = ThreadInfo.from(cd); 114 throw new RuntimeException("IllegalArgumentException not thrown"); 115 } catch (IllegalArgumentException e) {} 116 } 117 118 /* 119 * ThreadInfo of version N can accept lockedMonitors of version >= N 120 */ 121 @Test 122 public static void withNewMonitorInfoCompositeData() throws Exception { 123 CompositeData cd = Factory.makeThreadInfoWithNewMonitorInfo(); 124 ThreadInfo info = ThreadInfo.from(cd); 125 checkThreadInfo(info); 126 } 127 128 /* 129 * Test CompositeData representing JDK 5 ThreadInfo 130 */ 131 @Test 132 public static void createV5ThreadInfo() throws Exception { 133 CompositeData cd = Factory.makeThreadInfoV5CompositeData(); 134 ThreadInfo info = ThreadInfo.from(cd); 135 checkThreadInfoV5(info); 136 } 137 138 /* 139 * Test ThreadInfoCompositeData.toCompositeData 140 */ 141 @Test 142 public static void internalToCompositeData() throws Exception { 143 CompositeData cd = Factory.makeThreadInfoCompositeData(); 144 ThreadInfo info = ThreadInfo.from(cd); 145 cd = sun.management.ThreadInfoCompositeData.toCompositeData(info); 146 info = ThreadInfo.from(cd); 147 checkThreadInfo(info); 148 } 149 150 static void checkThreadInfoV5(ThreadInfo info) { 151 Object[] values = Factory.VALUES; 152 153 if (info.getThreadId() != ((Long) values[THREAD_ID]).longValue()) { 154 throw new RuntimeException("Thread Id = " + info.getThreadId() + 155 " expected = " + values[THREAD_ID]); 156 } 157 if (!info.getThreadName().equals(values[THREAD_NAME])) { 158 throw new RuntimeException("Thread Name = " + 159 info.getThreadName() + " expected = " + values[THREAD_NAME]); 160 } 161 if (info.getThreadState() != Thread.State.RUNNABLE) { 162 throw new RuntimeException("Thread Name = " + 163 info.getThreadName() + " expected = " + Thread.State.RUNNABLE); 164 } 165 if (info.getBlockedTime() != ((Long) values[BLOCKED_TIME]).longValue()) { 166 throw new RuntimeException("blocked time = " + 167 info.getBlockedTime() + 168 " expected = " + values[BLOCKED_TIME]); 169 } 170 if (info.getBlockedCount() != ((Long) values[BLOCKED_COUNT]).longValue()) { 171 throw new RuntimeException("blocked count = " + 172 info.getBlockedCount() + 173 " expected = " + values[BLOCKED_COUNT]); 174 } 175 if (info.getWaitedTime() != ((Long) values[WAITED_TIME]).longValue()) { 176 throw new RuntimeException("waited time = " + 177 info.getWaitedTime() + 178 " expected = " + values[WAITED_TIME]); 179 } 180 if (info.getWaitedCount() != ((Long) values[WAITED_COUNT]).longValue()) { 181 throw new RuntimeException("waited count = " + 182 info.getWaitedCount() + 183 " expected = " + values[WAITED_COUNT]); 184 } 185 if (!info.getLockName().equals(values[LOCK_NAME])) { 186 throw new RuntimeException("Lock Name = " + 187 info.getLockName() + " expected = " + values[LOCK_NAME]); 188 } 189 if (info.getLockOwnerId() != 190 ((Long) values[LOCK_OWNER_ID]).longValue()) { 191 throw new RuntimeException( 192 "LockOwner Id = " + info.getLockOwnerId() + 193 " expected = " + values[LOCK_OWNER_ID]); 194 } 195 if (!info.getLockOwnerName().equals(values[LOCK_OWNER_NAME])) { 196 throw new RuntimeException("LockOwner Name = " + 197 info.getLockOwnerName() + " expected = " + 198 values[LOCK_OWNER_NAME]); 199 } 200 201 checkStackTrace(info.getStackTrace()); 202 checkLockInfo(info.getLockInfo()); 203 } 204 205 static void checkThreadInfo(ThreadInfo info) { 206 Object[] values = Factory.VALUES; 207 208 checkThreadInfoV5(info); 209 210 if (!values[DAEMON].equals(info.isDaemon())) { 211 throw new RuntimeException("Daemon = " + 212 info.isDaemon() + " expected = " + values[DAEMON]); 213 } 214 } 215 216 private static void checkStackTrace(StackTraceElement[] s) { 217 if (s.length != 1) { 218 throw new RuntimeException("Stack Trace length = " + 219 s.length + " expected = 1"); 220 } 221 222 StackTraceElement s1 = STE; 223 StackTraceElement s2 = s[0]; 224 225 // these attributes may be null 226 if (!Objects.equals(s1.getClassLoaderName(), s2.getClassLoaderName())) { 227 throw new RuntimeException("Class loader name = " + 228 s2.getClassLoaderName() + " expected = " + s1.getClassLoaderName()); 229 } 230 if (!Objects.equals(s1.getModuleName(), s2.getModuleName())) { 231 throw new RuntimeException("Module name = " + 232 s2.getModuleName() + " expected = " + s1.getModuleName()); 233 } 234 if (!Objects.equals(s1.getModuleVersion(), s2.getModuleVersion())) { 235 throw new RuntimeException("Module version = " + 236 s2.getModuleVersion() + " expected = " + s1.getModuleVersion()); 237 } 238 239 if (!s1.getClassName().equals(s2.getClassName())) { 240 throw new RuntimeException("Class name = " + 241 s2.getClassName() + " expected = " + s1.getClassName()); 242 } 243 if (!s1.getMethodName().equals(s2.getMethodName())) { 244 throw new RuntimeException("Method name = " + 245 s2.getMethodName() + " expected = " + s1.getMethodName()); 246 } 247 if (!s1.getFileName().equals(s2.getFileName())) { 248 throw new RuntimeException("File name = " + 249 s2.getFileName() + " expected = " + s1.getFileName()); 250 } 251 if (s1.getLineNumber() != s2.getLineNumber()) { 252 throw new RuntimeException("Line number = " + 253 s2.getLineNumber() + " expected = " + s1.getLineNumber()); 254 } 255 } 256 257 private static void checkLockInfo(LockInfo li) { 258 if (!li.getClassName().equals(lockInfo.getClassName())) { 259 throw new RuntimeException("Class Name = " + 260 li.getClassName() + " expected = " + lockInfo.getClassName()); 261 } 262 if (li.getIdentityHashCode() != lockInfo.getIdentityHashCode()) { 263 throw new RuntimeException("Class Name = " + 264 li.getIdentityHashCode() + " expected = " + 265 lockInfo.getIdentityHashCode()); 266 } 267 } 268 269 @Test 270 public static void badNameCompositeData() throws Exception { 271 CompositeData cd = Factory.makeCompositeDataWithBadNames(); 272 try { 273 ThreadInfo info = ThreadInfo.from(cd); 274 throw new RuntimeException("IllegalArgumentException not thrown"); 275 } catch (IllegalArgumentException e) { } 276 } 277 278 @Test 279 public static void badTypeCompositeData() throws Exception { 280 CompositeData cd = Factory.makeCompositeDataWithBadTypes(); 281 282 try { 283 ThreadInfo info = ThreadInfo.from(cd); 284 throw new RuntimeException("IllegalArgumentException not thrown"); 285 } catch (IllegalArgumentException e) { } 286 } 287 288 private static final int THREAD_ID = 0; 289 private static final int THREAD_NAME = 1; 290 private static final int THREAD_STATE = 2; 291 private static final int BLOCKED_TIME = 3; 292 private static final int BLOCKED_COUNT = 4; 293 private static final int WAITED_TIME = 5; 294 private static final int WAITED_COUNT = 6; 295 private static final int LOCK_NAME = 7; 296 private static final int LOCK_OWNER_ID = 8; 297 private static final int LOCK_OWNER_NAME = 9; 298 private static final int STACK_TRACE = 10; 299 private static final int SUSPENDED = 11; 300 private static final int IN_NATIVE = 12; 301 // JDK 6 ThreadInfo attributes 302 private static final int LOCK_INFO = 13; 303 private static final int LOCKED_MONITORS = 14; 304 private static final int LOCKED_SYNCS = 15; 305 // JDK 9 ThreadInfo attributes 306 private static final int DAEMON = 16; 307 private static final int PRIORITY = 17; 308 309 private static class Factory { 310 311 static final CompositeType STE_COMPOSITE_TYPE; 312 static final CompositeType LOCK_INFO_COMPOSITE_TYPE; 313 static final CompositeType MONITOR_INFO_COMPOSITE_TYPE; 314 static final ArrayType STE_ARRAY_COMPOSITE_TYPE; 315 static final ArrayType LOCK_INFO_ARRAY_COMPOSITE_TYPE; 316 static final ArrayType MONITOR_INFO_ARRAY_COMPOSITE_TYPE; 317 318 static { 319 CompositeType steCType = null; 320 CompositeType lockInfoCType = null; 321 CompositeType monitorInfoCType = null; 322 ArrayType steArrayType = null; 323 ArrayType lockInfoArrayType = null; 324 ArrayType monitorInfoArrayType = null; 325 326 try { 327 steCType = (CompositeType) OpenTypeConverter.toOpenType(StackTraceElement.class); 328 lockInfoCType = (CompositeType) OpenTypeConverter.toOpenType(LockInfo.class); 329 monitorInfoCType = (CompositeType) OpenTypeConverter.toOpenType(MonitorInfo.class); 330 steArrayType = new ArrayType(1, steCType); 331 lockInfoArrayType = new ArrayType(1, lockInfoCType); 332 monitorInfoArrayType = new ArrayType(1, monitorInfoCType); 333 } catch (Exception e) { 334 throw new RuntimeException(e); 335 } 336 STE_COMPOSITE_TYPE = steCType; 337 LOCK_INFO_COMPOSITE_TYPE = lockInfoCType; 338 MONITOR_INFO_COMPOSITE_TYPE = monitorInfoCType; 339 STE_ARRAY_COMPOSITE_TYPE = steArrayType; 340 LOCK_INFO_ARRAY_COMPOSITE_TYPE = lockInfoArrayType; 341 MONITOR_INFO_ARRAY_COMPOSITE_TYPE = monitorInfoArrayType; 342 } 343 344 static CompositeData makeThreadInfoCompositeData() throws OpenDataException { 345 CompositeType ct = new CompositeType("MyCompositeType", 346 "CompositeType for ThreadInfo", 347 ITEM_NAMES, 348 ITEM_NAMES, 349 ITEM_TYPES); 350 return new CompositeDataSupport(ct, ITEM_NAMES, VALUES); 351 } 352 353 static CompositeData makeThreadInfoV5CompositeData() throws OpenDataException { 354 CompositeType ct = new CompositeType("MyCompositeType", 355 "CompositeType for JDK 5 ThreadInfo", 356 V5_ITEM_NAMES, 357 V5_ITEM_NAMES, 358 V5_ITEM_TYPES); 359 return new CompositeDataSupport(ct, V5_ITEM_NAMES, V5_VALUES); 360 } 361 362 static CompositeData makeCompositeDataWithBadTypes() throws OpenDataException { 363 OpenType[] badItemTypes = { 364 SimpleType.LONG, 365 SimpleType.STRING, 366 SimpleType.STRING, 367 SimpleType.LONG, 368 SimpleType.LONG, 369 SimpleType.LONG, 370 SimpleType.LONG, 371 SimpleType.STRING, 372 SimpleType.LONG, 373 SimpleType.STRING, 374 SimpleType.LONG, // bad type 375 SimpleType.BOOLEAN, 376 SimpleType.BOOLEAN, 377 SimpleType.LONG, // bad type 378 SimpleType.LONG, // bad type 379 SimpleType.LONG, // bad type 380 SimpleType.BOOLEAN, 381 SimpleType.INTEGER, 382 }; 383 384 CompositeType ct = 385 new CompositeType("Bad item types", 386 "CompositeType for ThreadInfo", 387 ITEM_NAMES, 388 ITEM_NAMES, 389 badItemTypes); 390 391 // Copy before mutating to avoid affecting other tests. 392 Object[] localValues = VALUES.clone(); 393 394 // patch values[STACK_TRACE] to Long 395 localValues[STACK_TRACE] = Long.valueOf(1000); 396 localValues[LOCK_INFO] = Long.valueOf(1000); 397 localValues[LOCKED_MONITORS] = Long.valueOf(1000); 398 localValues[LOCKED_SYNCS] = Long.valueOf(1000); 399 return new CompositeDataSupport(ct, ITEM_NAMES, localValues); 400 } 401 402 static CompositeData makeCompositeDataWithBadNames() throws OpenDataException { 403 String[] badItemNames = ITEM_NAMES.clone(); 404 badItemNames[STACK_TRACE] = "BadStackTrace"; // bad item name 405 406 CompositeType ct = new CompositeType("Bad item names", 407 "CompositeType for ThreadInfo", 408 badItemNames, 409 badItemNames, 410 ITEM_TYPES); 411 return new CompositeDataSupport(ct, 412 badItemNames, 413 VALUES); 414 } 415 416 /* 417 * Create a CompositeData of ThreadInfo without JDK 6 attributes 418 */ 419 static CompositeData makeCompositeDataMissingV6() throws OpenDataException { 420 String[] itemNames = concat(V5_ITEM_NAMES, V9_ITEM_NAMES).toArray(String[]::new); 421 OpenType[] itemTypes = concat(V5_ITEM_TYPES, V9_ITEM_TYPES).toArray(OpenType[]::new); 422 Object[] values = concat(V5_VALUES, V9_VALUES).toArray(Object[]::new); 423 424 CompositeType ct = 425 new CompositeType("InvalidCompositeType", 426 "CompositeType for ThreadInfo", 427 itemNames, 428 itemNames, 429 itemTypes); 430 return new CompositeDataSupport(ct, itemNames, values); 431 } 432 433 static CompositeData makeStackTraceElement() { 434 Object[] steValue = { 435 STE.getClassLoaderName(), 436 STE.getModuleName(), 437 STE.getModuleVersion(), 438 STE.getClassName(), 439 STE.getMethodName(), 440 STE.getFileName(), 441 Integer.valueOf(STE.getLineNumber()), 442 Boolean.valueOf(STE.isNativeMethod()), 443 }; 444 445 try { 446 return new CompositeDataSupport(STE_COMPOSITE_TYPE, 447 STE_ITEM_NAMES, 448 steValue); 449 } catch (OpenDataException e) { 450 throw new RuntimeException(e); 451 } 452 } 453 454 static CompositeData makeStackTraceElementV5() throws OpenDataException { 455 CompositeType steV5CType = 456 new CompositeType("JDK 5 StackTraceElement", 457 "CompositeType for JDK 5 StackTraceElement", 458 STE_V5_ITEM_NAMES, 459 STE_V5_ITEM_NAMES, 460 STE_V5_ITEM_TYPES); 461 462 Object[] steV5Value = { 463 STE.getClassName(), 464 STE.getMethodName(), 465 STE.getFileName(), 466 Integer.valueOf(STE.getLineNumber()), 467 Boolean.valueOf(STE.isNativeMethod()), 468 }; 469 470 return new CompositeDataSupport(steV5CType, STE_V5_ITEM_NAMES, steV5Value); 471 } 472 473 /* 474 * Create a CompositeData of ThreadInfo without JDK 5 StackTraceElement 475 */ 476 static CompositeData makeThreadInfoWithV5StackTrace() throws OpenDataException { 477 OpenType[] badTypes = ITEM_TYPES.clone(); 478 Object[] badValues = VALUES.clone(); 479 480 CompositeData[] stackTrace = new CompositeData[1]; 481 stackTrace[0] = makeStackTraceElementV5(); 482 badTypes[STACK_TRACE] = new ArrayType(1, stackTrace[0].getCompositeType()); 483 badValues[STACK_TRACE] = stackTrace; 484 CompositeType ct = new CompositeType("CompositeType", 485 "ThreadInfo with JDK 5 StackTraceElement", 486 ITEM_NAMES, 487 ITEM_NAMES, 488 badTypes); 489 return new CompositeDataSupport(ct, ITEM_NAMES, badValues); 490 } 491 492 /* 493 * Create MonitorInfo with JDK 5 StackTraceElement (i.e. JDK 6 MonitorInfo) 494 * The value of "lockedStackFrame" attribute is null to ensure that 495 * the validation is done. 496 */ 497 static CompositeData makeV6MonitorInfo() throws OpenDataException { 498 CompositeData steV5 = makeStackTraceElementV5(); 499 500 String[] names = MONITOR_INFO_COMPOSITE_TYPE.keySet().toArray(new String[0]); 501 OpenType[] types = new OpenType[names.length]; 502 for (int i=0; i < names.length; i++) { 503 String n = names[i]; 504 types[i] = "lockedStackFrame".equals(n) 505 ? steV5.getCompositeType() 506 : MONITOR_INFO_COMPOSITE_TYPE.getType(n); 507 } 508 509 CompositeType ctype = 510 new CompositeType("JDK 6 MonitorInfo", 511 "CompositeType for JDK 6 MonitorInfo", 512 names, 513 names, 514 types); 515 516 Object[] values = { 517 lockClassName, 518 lockIdentityHashCode, 519 -1, 520 null 521 }; 522 523 return new CompositeDataSupport(ctype, names, values); 524 } 525 526 /* 527 * Create a CompositeData of ThreadInfo with incompatible MonitorInfo 528 */ 529 static CompositeData makeThreadInfoWithIncompatibleMonitorInfo() throws OpenDataException { 530 OpenType[] badTypes = ITEM_TYPES.clone(); 531 Object[] badValues = VALUES.clone(); 532 533 CompositeData[] lockedMonitors = new CompositeData[1]; 534 lockedMonitors[0] = makeV6MonitorInfo(); 535 badTypes[LOCKED_MONITORS] = new ArrayType(1, lockedMonitors[0].getCompositeType()); 536 badValues[LOCKED_MONITORS] = lockedMonitors; 537 CompositeType ct = new CompositeType("CompositeType", 538 "ThreadInfo with incompatible MonitorInfo", 539 ITEM_NAMES, 540 ITEM_NAMES, 541 badTypes); 542 return new CompositeDataSupport(ct, ITEM_NAMES, badValues); 543 } 544 545 static CompositeData makeNewMonitorInfo() throws OpenDataException { 546 String[] names = Stream.concat(MONITOR_INFO_COMPOSITE_TYPE.keySet().stream(), 547 Stream.of("extra")).toArray(String[]::new); 548 OpenType[] types = new OpenType[names.length]; 549 for (int i=0; i < names.length; i++) { 550 String n = names[i]; 551 types[i] = "extra".equals(n) 552 ? SimpleType.STRING 553 : MONITOR_INFO_COMPOSITE_TYPE.getType(n); 554 } 555 556 CompositeType compositeType = 557 new CompositeType("JDK X MonitorInfo", 558 "CompositeType for JDK X MonitorInfo", 559 names, 560 names, 561 types); 562 563 Object[] values = { 564 lockClassName, 565 lockIdentityHashCode, 566 Integer.valueOf(1), 567 makeStackTraceElement(), 568 "extra" 569 }; 570 571 return new CompositeDataSupport(compositeType, names, values); 572 } 573 574 /* 575 * Create a CompositeData of ThreadInfo with a newer version of MonitorInfo 576 */ 577 static CompositeData makeThreadInfoWithNewMonitorInfo() throws OpenDataException { 578 OpenType[] types = ITEM_TYPES.clone(); 579 Object[] badValues = VALUES.clone(); 580 581 CompositeData[] lockedMonitors = new CompositeData[1]; 582 lockedMonitors[0] = makeNewMonitorInfo(); 583 types[LOCKED_MONITORS] = new ArrayType(1, lockedMonitors[0].getCompositeType()); 584 badValues[LOCKED_MONITORS] = lockedMonitors; 585 CompositeType ct = new CompositeType("CompositeType", 586 "ThreadInfo with JDK 5 MonitorInfo", 587 ITEM_NAMES, 588 ITEM_NAMES, 589 types); 590 return new CompositeDataSupport(ct, ITEM_NAMES, badValues); 591 } 592 593 static CompositeData makeLockInfo() { 594 Object[] lockInfoValue = { 595 lockInfo.getClassName(), 596 lockInfo.getIdentityHashCode(), 597 }; 598 599 try { 600 return new CompositeDataSupport(LOCK_INFO_COMPOSITE_TYPE, 601 LOCK_INFO_ITEM_NAMES, 602 lockInfoValue); 603 } catch (OpenDataException e) { 604 throw new RuntimeException(e); 605 } 606 } 607 608 static CompositeData[] makeLockedSynchronizers() { 609 CompositeData[] lockedSyncs = new CompositeData[1]; 610 lockedSyncs[0] = makeLockInfo(); 611 return lockedSyncs; 612 } 613 614 static CompositeData[] makeLockedMonitors() { 615 CompositeData[] lockedMonitorsCD = new CompositeData[1]; 616 617 Object[] lockedMonitorsValue = { 618 lockInfo.getClassName(), 619 lockInfo.getIdentityHashCode(), 620 makeStackTraceElement(), 621 Integer.valueOf(1), 622 }; 623 try { 624 lockedMonitorsCD[0] = 625 new CompositeDataSupport(MONITOR_INFO_COMPOSITE_TYPE, 626 LOCKED_MONITORS_ITEM_NAMES, 627 lockedMonitorsValue); 628 } catch (OpenDataException e) { 629 throw new RuntimeException(e); 630 } 631 return lockedMonitorsCD; 632 } 633 634 static final String[] V5_ITEM_NAMES = { 635 "threadId", 636 "threadName", 637 "threadState", 638 "blockedTime", 639 "blockedCount", 640 "waitedTime", 641 "waitedCount", 642 "lockName", 643 "lockOwnerId", 644 "lockOwnerName", 645 "stackTrace", 646 "suspended", 647 "inNative", 648 }; 649 650 static final String[] V6_ITEM_NAMES = { 651 "lockInfo", 652 "lockedMonitors", 653 "lockedSynchronizers", 654 }; 655 656 static final String[] V9_ITEM_NAMES = { 657 "daemon", 658 "priority", 659 }; 660 661 static final OpenType[] V5_ITEM_TYPES = { 662 SimpleType.LONG, 663 SimpleType.STRING, 664 SimpleType.STRING, 665 SimpleType.LONG, 666 SimpleType.LONG, 667 SimpleType.LONG, 668 SimpleType.LONG, 669 SimpleType.STRING, 670 SimpleType.LONG, 671 SimpleType.STRING, 672 STE_ARRAY_COMPOSITE_TYPE, 673 SimpleType.BOOLEAN, 674 SimpleType.BOOLEAN, 675 }; 676 677 static final OpenType[] V6_ITEM_TYPES = { 678 LOCK_INFO_COMPOSITE_TYPE, 679 MONITOR_INFO_ARRAY_COMPOSITE_TYPE, 680 LOCK_INFO_ARRAY_COMPOSITE_TYPE, 681 }; 682 683 static final OpenType[] V9_ITEM_TYPES = { 684 SimpleType.BOOLEAN, 685 SimpleType.INTEGER, 686 }; 687 688 static final String[] STE_ITEM_NAMES = { 689 "classLoaderName", 690 "moduleName", 691 "moduleVersion", 692 "className", 693 "methodName", 694 "fileName", 695 "lineNumber", 696 "nativeMethod", 697 }; 698 699 static final String[] STE_V5_ITEM_NAMES = Arrays.copyOfRange(STE_ITEM_NAMES, 3, 8); 700 701 static final OpenType[] STE_V5_ITEM_TYPES = { 702 SimpleType.STRING, 703 SimpleType.STRING, 704 SimpleType.STRING, 705 SimpleType.INTEGER, 706 SimpleType.BOOLEAN 707 }; 708 709 static final String[] LOCK_INFO_ITEM_NAMES = { 710 "className", 711 "identityHashCode", 712 }; 713 714 static final String[] LOCKED_MONITORS_ITEM_NAMES = { 715 LOCK_INFO_ITEM_NAMES[0], 716 LOCK_INFO_ITEM_NAMES[1], 717 "lockedStackFrame", 718 "lockedStackDepth", 719 }; 720 721 static final Object[] V5_VALUES = { 722 Long.valueOf(100), 723 "FooThread", 724 "RUNNABLE", 725 Long.valueOf(200), 726 Long.valueOf(10), 727 Long.valueOf(300), 728 Long.valueOf(20), 729 lockName, 730 Long.valueOf(99), 731 "BarThread", 732 new CompositeData[] { makeStackTraceElement() }, 733 Boolean.valueOf(false), 734 Boolean.valueOf(false), 735 }; 736 737 static final Object[] V6_VALUES = { 738 makeLockInfo(), 739 makeLockedMonitors(), 740 makeLockedSynchronizers(), 741 }; 742 743 static final Object[] V9_VALUES = { 744 Boolean.valueOf(true), 745 Thread.NORM_PRIORITY, 746 }; 747 748 static final String[] ITEM_NAMES = 749 concat(V5_ITEM_NAMES, V6_ITEM_NAMES, V9_ITEM_NAMES).toArray(String[]::new); 750 751 static final OpenType[] ITEM_TYPES = 752 concat(V5_ITEM_TYPES, V6_ITEM_TYPES, V9_ITEM_TYPES).toArray(OpenType[]::new); 753 754 static final Object[] VALUES = 755 concat(V5_VALUES, V6_VALUES, V9_VALUES).toArray(Object[]::new); 756 757 static <T> Stream<T> concat(T[]... streams) { 758 return Stream.of(streams).flatMap(a -> Arrays.stream(a)); 759 } 760 } 761 }