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 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.Objects; 43 44 public 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 }