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 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 (!s1.getMethodName().equals(s2.getMethodName())) { 177 throw new RuntimeException("Method name = " + 178 s2.getMethodName() + " expected = " + s1.getMethodName()); 179 } 180 if (!s1.getFileName().equals(s2.getFileName())) { 181 throw new RuntimeException("File name = " + 182 s2.getFileName() + " expected = " + s1.getFileName()); 183 } 184 if (s1.getLineNumber() != s2.getLineNumber()) { 185 throw new RuntimeException("Line number = " + 186 s2.getLineNumber() + " expected = " + s1.getLineNumber()); 187 } 188 } 189 190 private static void checkLockInfo(LockInfo li) 191 throws Exception { 192 if (!li.getClassName().equals(lockInfo.getClassName())) { 193 throw new RuntimeException("Class Name = " + 194 li.getClassName() + " expected = " + lockInfo.getClassName()); 195 } 196 if (li.getIdentityHashCode() != lockInfo.getIdentityHashCode()) { 197 throw new RuntimeException("Class Name = " + 198 li.getIdentityHashCode() + " expected = " + 199 lockInfo.getIdentityHashCode()); 200 } 201 } 202 203 public static void badNameCompositeData() throws Exception { 204 CompositeType ct = 205 new CompositeType("MyCompositeType", 206 "CompositeType for ThreadInfo", 207 badItemNames, 208 badItemNames, 209 validItemTypes); 210 CompositeData cd = 211 new CompositeDataSupport(ct, 212 badItemNames, 213 values); 214 215 try { 216 ThreadInfo info = ThreadInfo.from(cd); 217 } catch (IllegalArgumentException e) { 218 System.out.println("Expected exception: " + 219 e.getMessage()); 220 return; 221 } 222 throw new RuntimeException( 223 "IllegalArgumentException not thrown"); 224 } 225 226 public static void badTypeCompositeData() throws Exception { 227 CompositeType ct = 228 new CompositeType("MyCompositeType", 229 "CompositeType for ThreadInfo", 230 validItemNames, 231 validItemNames, 232 badItemTypes); 233 234 // patch values[STACK_TRACE] to Long 235 values[STACK_TRACE] = new Long(1000); 236 values[LOCK_INFO] = new Long(1000); 237 CompositeData cd = 238 new CompositeDataSupport(ct, 239 validItemNames, 240 values); 241 242 try { 243 ThreadInfo info = ThreadInfo.from(cd); 244 } catch (IllegalArgumentException e) { 245 System.out.println("Expected exception: " + 246 e.getMessage()); 247 return; 248 } 249 throw new RuntimeException( 250 "IllegalArgumentException not thrown"); 251 } 252 253 private static final int THREAD_ID = 0; 254 private static final int THREAD_NAME = 1; 255 private static final int THREAD_STATE = 2; 256 private static final int BLOCKED_TIME = 3; 257 private static final int BLOCKED_COUNT = 4; 258 private static final int WAITED_TIME = 5; 259 private static final int WAITED_COUNT = 6; 260 private static final int LOCK_NAME = 7; 261 private static final int LOCK_OWNER_ID = 8; 262 private static final int LOCK_OWNER_NAME = 9; 263 private static final int STACK_TRACE = 10; 264 private static final int SUSPENDED = 11; 265 private static final int IN_NATIVE = 12; 266 private static final int NUM_V5_ATTS = 13; 267 // JDK 6.0 ThreadInfo attributes 268 private static final int LOCK_INFO = 13; 269 // JDK 9.0 ThreadInfo attributes 270 private static final int DAEMON = 14; 271 private static final int PRIORITY = 15; 272 273 private static final String[] validItemNames = { 274 "threadId", 275 "threadName", 276 "threadState", 277 "blockedTime", 278 "blockedCount", 279 "waitedTime", 280 "waitedCount", 281 "lockName", 282 "lockOwnerId", 283 "lockOwnerName", 284 "stackTrace", 285 "suspended", 286 "inNative", 287 "lockInfo", 288 "daemon", 289 "priority", 290 }; 291 292 private static OpenType[] validItemTypes = { 293 SimpleType.LONG, 294 SimpleType.STRING, 295 SimpleType.STRING, 296 SimpleType.LONG, 297 SimpleType.LONG, 298 SimpleType.LONG, 299 SimpleType.LONG, 300 SimpleType.STRING, 301 SimpleType.LONG, 302 SimpleType.STRING, 303 null, // ArrayType for StackTraceElement[] 304 SimpleType.BOOLEAN, 305 SimpleType.BOOLEAN, 306 null, // CompositeType for LockInfo 307 SimpleType.BOOLEAN, 308 SimpleType.INTEGER, 309 }; 310 311 private static Object[] values = { 312 new Long(100), 313 "FooThread", 314 "RUNNABLE", 315 new Long(200), 316 new Long(10), 317 new Long(300), 318 new Long(20), 319 lockName, 320 new Long(99), 321 "BarThread", 322 steCD, 323 new Boolean(false), 324 new Boolean(false), 325 null, // To be initialized to lockInfoCD 326 new Boolean(false), 327 Thread.NORM_PRIORITY, 328 }; 329 330 private static final String[] steItemNames = { 331 "className", 332 "methodName", 333 "fileName", 334 "lineNumber", 335 "nativeMethod", 336 }; 337 338 private static final String[] lockInfoItemNames = { 339 "className", 340 "identityHashCode", 341 }; 342 343 static { 344 // create stack trace element 345 ste[0] = new StackTraceElement("FooClass", "getFoo", "Foo.java", 100); 346 347 // initialize the ste[0] and values and validItemTypes 348 try { 349 CompositeType steCType = (CompositeType) 350 OpenTypeConverter.toOpenType(StackTraceElement.class); 351 validItemTypes[STACK_TRACE] = new ArrayType(1, steCType); 352 353 final Object[] steValue = { 354 ste[0].getClassName(), 355 ste[0].getMethodName(), 356 ste[0].getFileName(), 357 new Integer(ste[0].getLineNumber()), 358 new Boolean(ste[0].isNativeMethod()), 359 }; 360 361 steCD[0] = 362 new CompositeDataSupport(steCType, 363 steItemNames, 364 steValue); 365 366 CompositeType lockInfoCType = (CompositeType) 367 OpenTypeConverter.toOpenType(LockInfo.class); 368 validItemTypes[LOCK_INFO] = lockInfoCType; 369 370 final Object[] lockInfoValue = { 371 lockInfo.getClassName(), 372 lockInfo.getIdentityHashCode(), 373 }; 374 375 values[LOCK_INFO] = 376 new CompositeDataSupport(lockInfoCType, 377 lockInfoItemNames, 378 lockInfoValue); 379 } catch (Exception e) { 380 throw new RuntimeException(e); 381 } 382 } 383 384 private static final String[] badItemNames = { 385 "threadId", 386 "threadName", 387 "threadState", 388 "blockedTime", 389 "blockedCount", 390 "waitedTime", 391 "waitedCount", 392 "lockName", 393 "lockOwnerId", 394 "lockOwnerName", 395 "BadStackTrace", // bad item name 396 "suspended", 397 "inNative", 398 "lockInfo", 399 "daemon", 400 "priority", 401 }; 402 private static final OpenType[] badItemTypes = { 403 SimpleType.LONG, 404 SimpleType.STRING, 405 SimpleType.STRING, 406 SimpleType.LONG, 407 SimpleType.LONG, 408 SimpleType.LONG, 409 SimpleType.LONG, 410 SimpleType.STRING, 411 SimpleType.LONG, 412 SimpleType.STRING, 413 SimpleType.LONG, // bad type 414 SimpleType.BOOLEAN, 415 SimpleType.BOOLEAN, 416 SimpleType.LONG, // bad type 417 SimpleType.BOOLEAN, 418 SimpleType.INTEGER, 419 }; 420 421 }