1 /* 2 * Copyright (c) 2003, 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 package nsk.monitoring.share; 24 25 import java.lang.management.*; 26 import javax.management.*; 27 import javax.management.openmbean.*; 28 import java.util.*; 29 30 import nsk.share.*; 31 32 /** 33 * <code>MemoryMonitor</code> class is a wrapper of <code>MemoryMXBean</code> and 34 * <code>MemoryPoolMXBean</code> interfaces. Depending on command line arguments, 35 * an instance of this class redirects invocations to the 36 * <code>MemoryMXBean</code> (or <code>MemoryPoolMXBean</code>) interface. If 37 * <code>-testMode="directly"</code> option is set, this instance directly 38 * invokes corresponding method of the <code>MemoryMXBean</code> (or 39 * <code>MemoryPoolMXBean</code>) interface. If <code>-testMode="server"</code> 40 * option is set it will make invocations via MBeanServer. 41 * 42 * @see ArgumentHandler 43 */ 44 public class MemoryMonitor extends Monitor implements NotificationListener, 45 NotificationFilter { 46 47 // Constants to define type of memory that will be allocated in 48 // MemoryMonitor. For heap memory objects will be allocated; for nonheap 49 // type classes will be loaded; for mixed type -- both (objects will be 50 // allocated and classes will be loaded). 51 public final static String HEAP_TYPE = "heap"; 52 public final static String NONHEAP_TYPE = "nonheap"; 53 public final static String MIXED_TYPE = "mixed"; 54 // Names of the attributes of MemoryMXBean 55 private final static String POOL_TYPE = "Type"; 56 private final static String POOL_RESET_PEAK = "resetPeakUsage"; 57 private final static String POOL_PEAK = "PeakUsage"; 58 private final static String POOL_VALID = "Valid"; 59 private final static String POOL_U = "Usage"; 60 private final static String UT = "UsageThreshold"; 61 private final static String UT_COUNT = "UsageThresholdCount"; 62 private final static String UT_SUPPORT = "UsageThresholdSupported"; 63 private final static String UT_EXCEEDED = "UsageThresholdExceeded"; 64 private final static String POOL_CU = "CollectionUsage"; 65 private final static String CT = "CollectionUsageThreshold"; 66 private final static String CT_COUNT = "CollectionUsageThresholdCount"; 67 private final static String CT_SUPPORT = "CollectionUsageThresholdSupported"; 68 private final static String CT_EXCEEDED = "CollectionUsageThresholdExceeded"; 69 // Varibales to store options that are passed to the test 70 private static String memory; 71 private static int mode; 72 private static boolean isNotification; 73 private static boolean isUsageThreshold; 74 private static volatile boolean passed = true; 75 private Polling polling = new Polling(); 76 77 static { 78 Monitor.logPrefix = "MemoryMonitor > "; 79 } 80 81 /** 82 * Creates a new <code>MemoryMonitor</code> object. 83 * 84 * @param log <code>Log</code> object to print info to. 85 * @param handler <code>ArgumentHandler</code> object that saves 86 * all info about test's arguments. 87 * 88 */ MemoryMonitor(Log log, ArgumentHandler handler)89 public MemoryMonitor(Log log, ArgumentHandler handler) { 90 super(log, handler); 91 92 memory = handler.getTestedMemory(); 93 mode = getTestMode(); 94 isNotification = (handler.MON_NOTIF.equals(handler.getMonitoring())); 95 isUsageThreshold = (handler.TH_USAGE.equals(handler.getThreshold())); 96 97 String s = "\t(This setting is used in lowmem* tests only)"; 98 99 display("Memory:\t" + handler.getTestedMemory() + s); 100 display("Monitoring:\t" + handler.getMonitoring() + s); 101 display("Threshold:\t" + handler.getThreshold() + s); 102 display("Timeout:\t" + handler.getTimeout() + s); 103 } 104 105 /** 106 * Returns <code>true</code> if no failures were revealed during the test, 107 * <code>false</code> otherwise. 108 * 109 * @return <code>true</code> if no failures were revealed during the test, 110 * <code>false</code> otherwise. 111 * 112 */ getPassedStatus()113 public boolean getPassedStatus() { 114 return passed; 115 } 116 117 /** 118 * Enables memory monitoring. 119 * <p> 120 * If notification type of monitoring is chosen, the method adds {@link 121 * javax.management.NotificationListener 122 * <code>javax.management.NotificationListener</code>} to enables low 123 * memory detection support. If monitoring type is polling, a new thread 124 * that manages the low memory detection is started. 125 * 126 * @throws InstanceNotFoundException The MemoryMXBean is not registered on 127 * the server. 128 */ enableMonitoring()129 public void enableMonitoring() throws InstanceNotFoundException { 130 if (isNotification) { 131 switch (mode) { 132 case DIRECTLY_MODE: 133 MemoryMXBean mbean = ManagementFactory.getMemoryMXBean(); 134 NotificationEmitter emitter = (NotificationEmitter) mbean; 135 emitter.addNotificationListener(this, this, null); 136 break; 137 138 case SERVER_MODE: 139 case PROXY_MODE: 140 getMBeanServer().addNotificationListener(mbeanObjectName, 141 this, this, null); 142 break; 143 144 default: 145 throw new TestBug("Unknown testMode " + mode); 146 } 147 } else { 148 149 // Polling 150 // Start a thread that will manage all test modes 151 polling.start(); 152 153 } 154 } // enableMonitoring() 155 156 /** 157 * Disables memory monitoring. 158 * <p> 159 * If monitoring type is polling, the thread that manages the low memory 160 * detection is stopped. 161 */ disableMonitoring()162 public void disableMonitoring() { 163 if (!isNotification) { 164 165 // Stop polling thread 166 polling.goOn = false; 167 } 168 } // disableMonitoring() 169 170 /** 171 * Updates thresholds. Thresholds values for all pools will be greater 172 * than <code>used</code> value. 173 * <p> 174 * If <code>usage</code> thresholds are chosen, the method updates just 175 * pools that support usage thresholds. If <code>collection</code> 176 * thresholds are chosen, the method updates memory pools that support 177 * collection usage thresholds. 178 * 179 * This method is synchronized because it may be invoked from 180 * <code>handleNotification</code> which is potentially done from 181 * multiple threads. 182 */ updateThresholds()183 public synchronized void updateThresholds() { 184 if (isUsageThreshold) { 185 updateUsageThresholds(); 186 } else { 187 updateCollectionThresholds(); 188 } 189 } 190 191 /** 192 * Reset thresholds. Thresholds values for all pools will be 1. 193 * If <code>usage</code> thresholds are chosen, the method updates just 194 * pools that support usage thresholds. If <code>collection</code> 195 * thresholds are chosen, the method updates memory pools that support 196 * collection usage thresholds. 197 * 198 * This method is synchronized because it may be invoked from 199 * multiple threads. 200 */ resetThresholds(MemoryType type)201 public synchronized void resetThresholds(MemoryType type) { 202 List pools = getMemoryPoolMBeans(); 203 for (int i = 0; i < pools.size(); i++) { 204 Object pool = pools.get(i); 205 if (isUsageThresholdSupported(pool)) { 206 if (getType(pool).equals(type)) { 207 setUsageThreshold(pool, 1); 208 } 209 } 210 } 211 } 212 213 /** 214 * The method is invoked before sending the notification to the listener. 215 * 216 * @param notification The notification to be sent. 217 * @return <i>true</i> if the notification has to be sent to the listener; 218 * <i>false</i> otherwise. 219 * 220 * @see javax.management.NotificationFilter 221 */ isNotificationEnabled(Notification notification)222 public boolean isNotificationEnabled(Notification notification) { 223 String type = notification.getType(); 224 String usage = MemoryNotificationInfo.MEMORY_THRESHOLD_EXCEEDED; 225 String collection = MemoryNotificationInfo.MEMORY_COLLECTION_THRESHOLD_EXCEEDED; 226 227 if (isUsageThreshold) { 228 return type.equals(usage); 229 } else { 230 return type.equals(collection); 231 } 232 } // isNotificationEnabled() 233 234 /** 235 * The method is invoked when a JMX notification occurs. 236 * 237 * @param notification The notification to be sent. 238 * @param handback An opaque object which helps the listener to associate 239 * information regarding the MBean emitter. 240 * @see javax.management.NotificationListener 241 */ handleNotification(Notification notification, Object handback)242 public void handleNotification(Notification notification, Object handback) { 243 CompositeData data = (CompositeData) notification.getUserData(); 244 MemoryNotificationInfo mn = MemoryNotificationInfo.from(data); 245 246 display(mn.getCount() + " notification \"" + notification.getMessage() 247 + "\" is caught on " + (new Date(notification.getTimeStamp())) 248 + " by " + mn.getPoolName() + " (" + mn.getUsage() + ")"); 249 updateThresholds(); 250 } // handleNotification() 251 252 /** 253 * Redirects the invocation to {@link 254 * java.lang.management.MemoryPoolMXBean#resetPeakUsage 255 * <code>MemoryPoolMXBean.resetPeakUsage()</code>}. 256 * 257 * @param poolObject reference to the pool. The pool may be specified 258 * either by <code>ObjectName</code>, or 259 * <code>MemoryPoolMXBean</code>. 260 */ resetPeakUsage(Object poolObject)261 public void resetPeakUsage(Object poolObject) { 262 switch (mode) { 263 case DIRECTLY_MODE: 264 MemoryPoolMXBean directPool = (MemoryPoolMXBean) poolObject; 265 directPool.resetPeakUsage(); 266 break; 267 268 case SERVER_MODE: 269 ObjectName serverPool = (ObjectName) poolObject; 270 271 try { 272 getMBeanServer().invoke(serverPool, POOL_RESET_PEAK, 273 null, null); 274 } catch (Exception e) { 275 e.printStackTrace(logger.getOutStream()); 276 throw new Failure(e); 277 } 278 break; 279 280 case PROXY_MODE: 281 MemoryPoolMXBean proxyPool = (MemoryPoolMXBean) poolObject; 282 proxyPool.resetPeakUsage(); 283 break; 284 285 default: 286 throw new TestBug("Unknown testMode " + mode); 287 } 288 } // resetPeakUsage() 289 290 /** 291 * Redirects the invocation to {@link 292 * java.lang.management.MemoryPoolMXBean#getPeakUsage 293 * <code>MemoryPoolMXBean.getPeakUsage()</code>}. 294 * 295 * @param poolObject reference to the pool. The pool may be specified 296 * either by <code>ObjectName</code>, or 297 * <code>MemoryPoolMXBean</code>. 298 * @return a <code>MemoryUsage</code> object representing the peak memory 299 * usage; <code>null</code> otherwise. 300 */ getPeakUsage(Object poolObject)301 public MemoryUsage getPeakUsage(Object poolObject) { 302 switch (mode) { 303 case DIRECTLY_MODE: 304 MemoryPoolMXBean directPool = (MemoryPoolMXBean) poolObject; 305 return directPool.getPeakUsage(); 306 307 case SERVER_MODE: 308 ObjectName serverPool = (ObjectName) poolObject; 309 return getMemoryUsageAttribute(serverPool, POOL_PEAK); 310 311 case PROXY_MODE: 312 MemoryPoolMXBean proxyPool = (MemoryPoolMXBean) poolObject; 313 return proxyPool.getPeakUsage(); 314 315 default: 316 throw new TestBug("Unknown testMode " + mode); 317 } 318 } // getPeakUsage() 319 320 /** 321 * Redirects the invocation to {@link 322 * java.lang.management.MemoryPoolMXBean#getUsage 323 * <code>MemoryPoolMXBean.getUsage()</code>}. 324 * 325 * @param poolObject reference to the pool. The pool may be specified 326 * either by <code>ObjectName</code>, or 327 * <code>MemoryPoolMXBean</code>. 328 * @return a <code>MemoryUsage</code> object; or <code>null</code> if this 329 * pool not valid. 330 */ getUsage(Object poolObject)331 public MemoryUsage getUsage(Object poolObject) { 332 switch (mode) { 333 case DIRECTLY_MODE: 334 MemoryPoolMXBean directPool = (MemoryPoolMXBean) poolObject; 335 return directPool.getUsage(); 336 337 case SERVER_MODE: 338 ObjectName serverPool = (ObjectName) poolObject; 339 return getUsageOnServer(serverPool); 340 341 case PROXY_MODE: 342 MemoryPoolMXBean proxyPool = (MemoryPoolMXBean) poolObject; 343 return proxyPool.getUsage(); 344 345 default: 346 throw new TestBug("Unknown testMode " + mode); 347 } 348 } // getUsage() 349 350 /** 351 * Redirects the invocation to {@link 352 * java.lang.management.MemoryPoolMXBean#getCollectionUsage 353 * <code>MemoryPoolMXBean.getCollectionUsage()</code>}. 354 * 355 * @param poolObject reference to the pool. The pool may be specified 356 * either by <code>ObjectName</code>, or 357 * <code>MemoryPoolMXBean</code>. 358 * @return a <code>MemoryUsage</code> object; or <code>null</code> if this 359 * method is not supported. 360 */ getCollectionUsage(Object poolObject)361 public MemoryUsage getCollectionUsage(Object poolObject) { 362 switch (mode) { 363 case DIRECTLY_MODE: 364 MemoryPoolMXBean directPool = (MemoryPoolMXBean) poolObject; 365 return directPool.getCollectionUsage(); 366 367 case SERVER_MODE: 368 ObjectName serverPool = (ObjectName) poolObject; 369 return getCollectionUsageOnServer(serverPool); 370 371 case PROXY_MODE: 372 MemoryPoolMXBean proxyPool = (MemoryPoolMXBean) poolObject; 373 return proxyPool.getCollectionUsage(); 374 375 default: 376 throw new TestBug("Unknown testMode " + mode); 377 } 378 } // getCollectionUsage() 379 380 /** 381 * Redirects the invocation to {@link 382 * java.lang.management.MemoryPoolMXBean#isValid 383 * <code>MemoryPoolMXBean.isValid()</code>}. 384 * 385 * @param poolObject reference to the pool. The pool may be specified 386 * either by <code>ObjectName</code>, or 387 * <code>MemoryPoolMXBean</code>. 388 * @return a <code>true</code> if the memory pool is valid in the running 389 * JVM; <code>null</code> otherwise. 390 */ isValid(Object poolObject)391 public boolean isValid(Object poolObject) { 392 switch (mode) { 393 case DIRECTLY_MODE: 394 MemoryPoolMXBean directPool = (MemoryPoolMXBean) poolObject; 395 return directPool.isValid(); 396 397 case SERVER_MODE: 398 ObjectName serverPool = (ObjectName) poolObject; 399 return getBooleanAttribute(serverPool, POOL_VALID); 400 401 case PROXY_MODE: 402 MemoryPoolMXBean proxyPool = (MemoryPoolMXBean) poolObject; 403 return proxyPool.isValid(); 404 405 default: 406 throw new TestBug("Unknown testMode " + mode); 407 } 408 } // isValid() 409 410 /** 411 * Redirects the invocation to {@link 412 * java.lang.management.MemoryPoolMXBean#isUsageThresholdSupported 413 * <code>MemoryPoolMXBean.isUsageThresholdSupported()</code>}. 414 * 415 * @param poolObject reference to the pool. The pool may be specified 416 * either by <code>ObjectName</code>, or 417 * <code>MemoryPoolMXBean</code>. 418 * @return a <code>true</code> if the memory pool supports usage threshold; 419 * <code>null</code> otherwise. 420 */ isUsageThresholdSupported(Object poolObject)421 public boolean isUsageThresholdSupported(Object poolObject) { 422 switch (mode) { 423 case DIRECTLY_MODE: 424 MemoryPoolMXBean directPool = (MemoryPoolMXBean) poolObject; 425 return directPool.isUsageThresholdSupported(); 426 427 case SERVER_MODE: 428 ObjectName serverPool = (ObjectName) poolObject; 429 return isUsageThresholdSupportedOnServer(serverPool); 430 431 case PROXY_MODE: 432 MemoryPoolMXBean proxyPool = (MemoryPoolMXBean) poolObject; 433 return proxyPool.isUsageThresholdSupported(); 434 435 default: 436 throw new TestBug("Unknown testMode " + mode); 437 } 438 } // isUsageThresholdSupported() 439 440 /** 441 * Redirects the invocation to {@link 442 * java.lang.management.MemoryPoolMXBean#isCollectionUsageThresholdSupported 443 * <code>MemoryPoolMXBean.isCollectionUsageThresholdSupported()</code>}. 444 * 445 * @param poolObject reference to the pool. The pool may be specified 446 * either by <code>ObjectName</code>, or 447 * <code>MemoryPoolMXBean</code>. 448 * @return a <code>true</code> if the memory pool supports collection 449 * usage threshold; <code>null</code> otherwise. 450 */ isCollectionThresholdSupported(Object poolObject)451 public boolean isCollectionThresholdSupported(Object poolObject) { 452 switch (mode) { 453 case DIRECTLY_MODE: 454 MemoryPoolMXBean directPool = (MemoryPoolMXBean) poolObject; 455 return directPool.isCollectionUsageThresholdSupported(); 456 457 case SERVER_MODE: 458 ObjectName serverPool = (ObjectName) poolObject; 459 return isCollectionThresholdSupportedOnServer(serverPool); 460 461 case PROXY_MODE: 462 MemoryPoolMXBean proxyPool = (MemoryPoolMXBean) poolObject; 463 return proxyPool.isCollectionUsageThresholdSupported(); 464 465 default: 466 throw new TestBug("Unknown testMode " + mode); 467 } 468 } // isCollectionThresholdSupported() 469 470 /** 471 * Redirects the invocation to {@link 472 * java.lang.management.MemoryPoolMXBean#isUsageThresholdExceeded 473 * <code>MemoryPoolMXBean.isUsageThresholdExceeded()</code>}. 474 * 475 * @param poolObject reference to the pool. The pool may be specified 476 * either by <code>ObjectName</code>, or 477 * <code>MemoryPoolMXBean</code>. 478 * @return a <code>true</code> if the memory usage of this pool reaches or 479 * exceeds the threshold value; <code>null</code> otherwise. 480 */ isUsageThresholdExceeded(Object poolObject)481 public boolean isUsageThresholdExceeded(Object poolObject) { 482 switch (mode) { 483 case DIRECTLY_MODE: 484 MemoryPoolMXBean directPool = (MemoryPoolMXBean) poolObject; 485 return directPool.isUsageThresholdExceeded(); 486 487 case SERVER_MODE: 488 ObjectName serverPool = (ObjectName) poolObject; 489 return isUsageThresholdExceededOnServer(serverPool); 490 491 case PROXY_MODE: 492 MemoryPoolMXBean proxyPool = (MemoryPoolMXBean) poolObject; 493 return proxyPool.isUsageThresholdExceeded(); 494 495 default: 496 throw new TestBug("Unknown testMode " + mode); 497 } 498 } // isUsageThresholdExceeded() 499 500 /** 501 * Redirects the invocation to {@link 502 * java.lang.management.MemoryPoolMXBean#isCollectionUsageThresholdExceeded 503 * <code>MemoryPoolMXBean.isCollectionUsageThresholdExceeded()</code>}. 504 * 505 * @param poolObject reference to the pool. The pool may be specified 506 * either by <code>ObjectName</code>, or 507 * <code>MemoryPoolMXBean</code>. 508 * @return a <code>true</code> if the memory usage of this pool reaches or 509 * exceeds the collection usage threshold value in the most recent 510 * collection; <code>null</code> otherwise. 511 */ isCollectionThresholdExceeded(Object poolObject)512 public boolean isCollectionThresholdExceeded(Object poolObject) { 513 switch (mode) { 514 case DIRECTLY_MODE: 515 MemoryPoolMXBean directPool = (MemoryPoolMXBean) poolObject; 516 return directPool.isCollectionUsageThresholdExceeded(); 517 518 case SERVER_MODE: 519 ObjectName serverPool = (ObjectName) poolObject; 520 return isCollectionThresholdExceededOnServer(serverPool); 521 522 case PROXY_MODE: 523 MemoryPoolMXBean proxyPool = (MemoryPoolMXBean) poolObject; 524 return proxyPool.isCollectionUsageThresholdExceeded(); 525 526 default: 527 throw new TestBug("Unknown testMode " + mode); 528 } 529 } // isCollectionThresholdExceeded() 530 531 /** 532 * Redirects the invocation to {@link 533 * java.lang.management.MemoryPoolMXBean#getUsageThreshold 534 * <code>MemoryPoolMXBean.getUsageThreshold()</code>}. 535 * 536 * @param poolObject reference to the pool. The pool may be specified 537 * either by <code>ObjectName</code>, or 538 * <code>MemoryPoolMXBean</code>. 539 * @return the usage threshold value of this memory pool in bytes. 540 */ getUsageThreshold(Object poolObject)541 public long getUsageThreshold(Object poolObject) { 542 switch (mode) { 543 case DIRECTLY_MODE: 544 MemoryPoolMXBean directPool = (MemoryPoolMXBean) poolObject; 545 return directPool.getUsageThreshold(); 546 547 case SERVER_MODE: 548 ObjectName serverPool = (ObjectName) poolObject; 549 return getUsageThresholdOnServer(serverPool); 550 551 case PROXY_MODE: 552 MemoryPoolMXBean proxyPool = (MemoryPoolMXBean) poolObject; 553 return proxyPool.getUsageThreshold(); 554 555 default: 556 throw new TestBug("Unknown testMode " + mode); 557 } 558 } // getUsageThreshold() 559 560 /** 561 * Redirects the invocation to {@link 562 * java.lang.management.MemoryPoolMXBean#getCollectionUsageThreshold 563 * <code>MemoryPoolMXBean.getCollectionUsageThreshold()</code>}. 564 * 565 * @param poolObject reference to the pool. The pool may be specified 566 * either by <code>ObjectName</code>, or 567 * <code>MemoryPoolMXBean</code>. 568 * @return the collection usage threshold value of this memory pool in 569 * bytes. 570 */ getCollectionThreshold(Object poolObject)571 public long getCollectionThreshold(Object poolObject) { 572 switch (mode) { 573 case DIRECTLY_MODE: 574 MemoryPoolMXBean directPool = (MemoryPoolMXBean) poolObject; 575 return directPool.getCollectionUsageThreshold(); 576 577 case SERVER_MODE: 578 ObjectName serverPool = (ObjectName) poolObject; 579 return getCollectionThresholdOnServer(serverPool); 580 581 case PROXY_MODE: 582 MemoryPoolMXBean proxyPool = (MemoryPoolMXBean) poolObject; 583 return proxyPool.getCollectionUsageThreshold(); 584 585 default: 586 throw new TestBug("Unknown testMode " + mode); 587 } 588 } // getCollectionThreshold() 589 590 /** 591 * Redirects the invocation to {@link 592 * java.lang.management.MemoryPoolMXBean#getUsageThresholdCount 593 * <code>MemoryPoolMXBean.getUsageThresholdCount()</code>}. 594 * 595 * @param poolObject reference to the pool. The pool may be specified 596 * either by <code>ObjectName</code>, or 597 * <code>MemoryPoolMXBean</code>. 598 * @return number of times that the memory usage has crossed its usage 599 * threshold value. 600 */ getUsageThresholdCount(Object poolObject)601 public long getUsageThresholdCount(Object poolObject) { 602 switch (mode) { 603 case DIRECTLY_MODE: 604 MemoryPoolMXBean directPool = (MemoryPoolMXBean) poolObject; 605 return directPool.getUsageThresholdCount(); 606 607 case SERVER_MODE: 608 ObjectName serverPool = (ObjectName) poolObject; 609 return getUsageThresholdCountOnServer(serverPool); 610 611 case PROXY_MODE: 612 MemoryPoolMXBean proxyPool = (MemoryPoolMXBean) poolObject; 613 return proxyPool.getUsageThresholdCount(); 614 615 default: 616 throw new TestBug("Unknown testMode " + mode); 617 } 618 } // getUsageThresholdCount() 619 620 /** 621 * Redirects the invocation to {@link 622 * java.lang.management.MemoryPoolMXBean#getCollectionUsageThresholdCount 623 * <code>MemoryPoolMXBean.getCollectionUsageThresholdCount()</code>}. 624 * 625 * @param poolObject reference to the pool. The pool may be specified 626 * either by <code>ObjectName</code>, or 627 * <code>MemoryPoolMXBean</code>. 628 * @return number of times that the memory usage has crossed its collection 629 * usage threshold value. 630 */ getCollectionThresholdCount(Object poolObject)631 public long getCollectionThresholdCount(Object poolObject) { 632 switch (mode) { 633 case DIRECTLY_MODE: 634 MemoryPoolMXBean directPool = (MemoryPoolMXBean) poolObject; 635 return directPool.getCollectionUsageThresholdCount(); 636 637 case SERVER_MODE: 638 ObjectName serverPool = (ObjectName) poolObject; 639 return getCollectionThresholdCountOnServer(serverPool); 640 641 case PROXY_MODE: 642 MemoryPoolMXBean proxyPool = (MemoryPoolMXBean) poolObject; 643 return proxyPool.getCollectionUsageThresholdCount(); 644 645 default: 646 throw new TestBug("Unknown testMode " + mode); 647 } 648 } // getCollectionThresholdCount() 649 650 /** 651 * Redirects the invocation to {@link 652 * java.lang.management.MemoryPoolMXBean#setUsageThreshold 653 * <code>MemoryPoolMXBean.setUsageThreshold()</code>}. 654 * 655 * @param poolObject reference to the pool. The pool may be specified 656 * either by <code>ObjectName</code>, or 657 * <code>MemoryPoolMXBean</code>. 658 * @param threshold the new threshold value. 659 */ setUsageThreshold(Object poolObject, long threshold)660 public void setUsageThreshold(Object poolObject, long threshold) { 661 switch (mode) { 662 case DIRECTLY_MODE: 663 MemoryPoolMXBean directPool = (MemoryPoolMXBean) poolObject; 664 directPool.setUsageThreshold(threshold); 665 break; 666 667 case SERVER_MODE: 668 ObjectName serverPool = (ObjectName) poolObject; 669 setUsageThresholdOnServer(serverPool, threshold); 670 break; 671 672 case PROXY_MODE: 673 MemoryPoolMXBean proxyPool = (MemoryPoolMXBean) poolObject; 674 proxyPool.setUsageThreshold(threshold); 675 break; 676 677 default: 678 throw new TestBug("Unknown testMode " + mode); 679 } 680 } // setUsageThreshold() 681 682 /** 683 * Redirects the invocation to {@link 684 * java.lang.management.MemoryPoolMXBean#setCollectionUsageThreshold 685 * <code>MemoryPoolMXBean.setCollectionUsageThreshold()</code>}. 686 * 687 * @param poolObject reference to the pool. The pool may be specified 688 * either by <code>ObjectName</code>, or 689 * <code>MemoryPoolMXBean</code>. 690 * @param threshold the new collection usage threshold value. 691 */ setCollectionThreshold(Object poolObject, long threshold)692 public void setCollectionThreshold(Object poolObject, long threshold) { 693 switch (mode) { 694 case DIRECTLY_MODE: 695 MemoryPoolMXBean directPool = (MemoryPoolMXBean) poolObject; 696 directPool.setCollectionUsageThreshold(threshold); 697 break; 698 699 case SERVER_MODE: 700 ObjectName serverPool = (ObjectName) poolObject; 701 setCollectionThresholdOnServer(serverPool, threshold); 702 break; 703 704 case PROXY_MODE: 705 MemoryPoolMXBean proxyPool = (MemoryPoolMXBean) poolObject; 706 proxyPool.setCollectionUsageThreshold(threshold); 707 break; 708 709 default: 710 throw new TestBug("Unknown testMode " + mode); 711 } 712 } // setCollectionThreshold() 713 714 /** 715 * Redirects the invocation to {@link 716 * java.lang.management.MemoryPoolMXBean#getName 717 * <code>MemoryPoolMXBean.getName()</code>}. 718 * 719 * @param poolObject reference to the pool. The pool may be specified 720 * either by <code>ObjectName</code>, or 721 * <code>MemoryPoolMXBean</code>. 722 * @return the name of the memory pool. 723 */ getName(Object poolObject)724 public String getName(Object poolObject) { 725 switch (mode) { 726 case DIRECTLY_MODE: 727 MemoryPoolMXBean directPool = (MemoryPoolMXBean) poolObject; 728 return directPool.getName(); 729 730 case SERVER_MODE: 731 ObjectName serverPool = (ObjectName) poolObject; 732 return serverPool.toString(); 733 734 case PROXY_MODE: 735 MemoryPoolMXBean proxyPool = (MemoryPoolMXBean) poolObject; 736 return proxyPool.getName(); 737 738 default: 739 throw new TestBug("Unknown testMode " + mode); 740 } 741 } // getName() 742 743 /** 744 * Redirects the invocation to {@link 745 * java.lang.management.MemoryPoolMXBean#getType 746 * <code>MemoryPoolMXBean.getType()</code>}. 747 * 748 * @param poolObject reference to the pool. The pool may be specified 749 * either by <code>ObjectName</code>, or 750 * <code>MemoryPoolMXBean</code>. 751 * @return the name of the memory pool. 752 */ getType(Object poolObject)753 public MemoryType getType(Object poolObject) { 754 switch (mode) { 755 case DIRECTLY_MODE: 756 MemoryPoolMXBean directPool = (MemoryPoolMXBean) poolObject; 757 return directPool.getType(); 758 759 case SERVER_MODE: 760 ObjectName serverPool = (ObjectName) poolObject; 761 return getType(serverPool); 762 763 case PROXY_MODE: 764 MemoryPoolMXBean proxyPool = (MemoryPoolMXBean) poolObject; 765 return proxyPool.getType(); 766 767 default: 768 throw new TestBug("Unknown testMode " + mode); 769 } 770 } 771 772 /** 773 * Redirects the invocation to {@link 774 * java.lang.management.ManagementFactory#getMemoryPoolMXBeans 775 * <code>ManagementFactory.getMemoryPoolMXBeans()</code>}. 776 * 777 * @return a list of <code>MemoryPoolMXBean</code> objects. 778 */ getMemoryPoolMBeans()779 public List<? extends Object> getMemoryPoolMBeans() { 780 switch (mode) { 781 case DIRECTLY_MODE: 782 return ManagementFactory.getMemoryPoolMXBeans(); 783 784 case SERVER_MODE: { 785 ObjectName[] names = getMemoryPoolMXBeansOnServer(); 786 ArrayList<ObjectName> list = new ArrayList<ObjectName>(); 787 788 for (int i = 0; i < names.length; i++) { 789 list.add(names[i]); 790 } 791 return list; 792 } 793 794 case PROXY_MODE: { 795 ObjectName[] names = getMemoryPoolMXBeansOnServer(); 796 ArrayList<MemoryPoolMXBean> list = new ArrayList<MemoryPoolMXBean>(); 797 798 for (int i = 0; i < names.length; i++) { 799 list.add(getProxy(names[i])); 800 } 801 return list; 802 } 803 804 default: 805 throw new TestBug("Unknown testMode " + mode); 806 } 807 } // getMemoryPoolMXBeans() 808 809 // ********************************************************************** 810 // 811 // Private methods 812 // 813 // ********************************************************************** getProxy(ObjectName objectName)814 private MemoryPoolMXBean getProxy(ObjectName objectName) { 815 try { 816 MemoryPoolMXBean proxy = (MemoryPoolMXBean) ManagementFactory.newPlatformMXBeanProxy( 817 getMBeanServer(), 818 objectName.toString(), 819 MemoryPoolMXBean.class); 820 return proxy; 821 } catch (Exception e) { 822 throw new Failure(e); 823 } 824 } 825 826 // Sets new usage threasholds in all pools that match the tested memory and 827 // support low memory detetion. A new value will be greater than used value 828 // for the pool. updateUsageThresholds()829 private void updateUsageThresholds() { 830 switch (mode) { 831 case DIRECTLY_MODE: 832 // we can use the same code here for direct and proxy modes 833 case PROXY_MODE: 834 List poolsMBean = ManagementFactory.getMemoryPoolMXBeans(); 835 836 for (int i = 0; i < poolsMBean.size(); i++) { 837 MemoryPoolMXBean pool = (MemoryPoolMXBean) poolsMBean.get(i); 838 if (!pool.isUsageThresholdSupported()) { 839 continue; 840 } 841 842 MemoryType mt = pool.getType(); 843 if ((!mt.equals(MemoryType.HEAP) 844 || !memory.equals(HEAP_TYPE)) 845 && (!mt.equals(MemoryType.NON_HEAP) 846 || !memory.equals(NONHEAP_TYPE)) 847 && !memory.equals(MIXED_TYPE)) { 848 continue; 849 } 850 851 // Yes! We got the pool that 852 // 1. supports usage threshold 853 // 2. has type that match tested type 854 // So, update the pool with new threshold 855 long oldT = pool.getUsageThreshold(); 856 MemoryUsage usage = pool.getUsage(); 857 long newT = newThreshold(usage, oldT, pool.getName()); 858 859 try { 860 pool.setUsageThreshold(newT); 861 } catch (IllegalArgumentException e) { 862 /* 863 * Max value might have changed since the call to newThreshold() 864 * above. If it has fallen below the value of newT, which is certainly 865 * possible, an exception like this one will be thrown from 866 * sun.management.MemoryPoolImpl.setUsageThreshold(): 867 * 868 * java.lang.IllegalArgumentException: Invalid threshold: 48332800 > max (47251456). 869 * 870 * We don't know the max value at the time of the failed call, and it 871 * might have changed since the call once more. So there is no point 872 * trying to detect whether the IllegalArgumentException had been 873 * justified, we cannot know it at this point. 874 * 875 * The best we can do is log the fact and continue. 876 */ 877 displayInfo("setUsageThreshold() failed with " + e + ", ignoring... ", 878 pool, 879 "current usage after the call to setUsageThreshold(): ", getUsage(pool), 880 "threshold: ", newT); 881 continue; 882 } 883 displayInfo("Usage threshold is set", pool, "usage: ", pool.getUsage(), "threshold: ", pool.getUsageThreshold()); 884 if (pool.getUsageThreshold() != newT) { 885 complain("Cannot reset usage threshold from " + oldT 886 + " to " + newT + " in pool " + pool.getName() + " " 887 + pool.getUsageThreshold()); 888 passed = false; 889 } 890 } // for i 891 break; 892 893 case SERVER_MODE: 894 ObjectName[] pools = getMemoryPoolMXBeansOnServer(); 895 896 for (int i = 0; i < pools.length; i++) { 897 if (!isUsageThresholdSupportedOnServer(pools[i])) { 898 continue; 899 } 900 901 MemoryType mt = getType(pools[i]); 902 if ((!mt.equals(MemoryType.HEAP) 903 || !memory.equals(HEAP_TYPE)) 904 && (!mt.equals(MemoryType.NON_HEAP) 905 || !memory.equals(NONHEAP_TYPE)) 906 && !memory.equals(MIXED_TYPE)) { 907 continue; 908 } 909 910 // Yes! We got the pool that 911 // 1. supports usage threshold 912 // 2. has type that match tested type 913 // So, update the pool with new threshold 914 long oldT = getUsageThreshold(pools[i]); 915 long newT = newThreshold(getUsageOnServer(pools[i]), oldT, 916 pools[i].toString()); 917 try { 918 setUsageThresholdOnServer(pools[i], newT); 919 } catch (Failure e) { 920 /* 921 * Max value might have changed since the call to newThreshold() 922 * above. If it has fallen below the value of newT, which is certainly 923 * possible, an exception like this one will be thrown from 924 * sun.management.MemoryPoolImpl.setUsageThreshold(): 925 * 926 * java.lang.IllegalArgumentException: Invalid threshold: 48332800 > max (47251456). 927 * 928 * and we'll catch Failure here as a result (it'll be thrown by 929 * Monitor.setLongAttribute). 930 * 931 * We don't know the max value at the time of the failed call, and it 932 * might have changed since the call once more. So there is no point 933 * trying to detect whether the IllegalArgumentException had been 934 * justified, we cannot know it at this point. 935 * 936 * The best we can do is log the fact and continue. 937 */ 938 displayInfo("setUsageThresholdOnServer() failed with " + e + ", ignoring... ", 939 pools[i], 940 "current usage after the call to setUsageThresholdOnServer(): ", getUsageOnServer(pools[i]), 941 "threshold: ", newT); 942 continue; 943 } 944 displayInfo("Usage threshold is set", null, "pool: ", pools[i], "usage:", getUsageOnServer(pools[i])); 945 if (getUsageThreshold(pools[i]) != newT) { 946 complain("Cannot reset usage threshold from " + oldT + " to " 947 + newT + " in pool " + pools[i].toString()); 948 passed = false; 949 } 950 } // for i 951 break; 952 953 default: 954 throw new TestBug("Unknown testMode " + mode); 955 } 956 } // updateUsageThresholds() 957 958 // Sets new collection usage threasholds in all pools that match the tested 959 // memory and support low memory detetion. A new value will be greater than 960 // used value for the pool. updateCollectionThresholds()961 private void updateCollectionThresholds() { 962 switch (mode) { 963 case DIRECTLY_MODE: 964 // we can use the same code here for direct and proxy modes 965 case PROXY_MODE: 966 List poolsMBean = ManagementFactory.getMemoryPoolMXBeans(); 967 968 for (int i = 0; i < poolsMBean.size(); i++) { 969 MemoryPoolMXBean pool = (MemoryPoolMXBean) poolsMBean.get(i); 970 if (!pool.isCollectionUsageThresholdSupported()) { 971 continue; 972 } 973 974 MemoryType mt = pool.getType(); 975 if ((!mt.equals(MemoryType.HEAP) 976 || !memory.equals(HEAP_TYPE)) 977 && (!mt.equals(MemoryType.NON_HEAP) 978 || !memory.equals(NONHEAP_TYPE)) 979 && !memory.equals(MIXED_TYPE)) { 980 continue; 981 } 982 983 // Yes! We got the pool that 984 // 1. supports collection threshold 985 // 2. has type that match tested type 986 // So, update the pool with new threshold 987 long oldT = pool.getCollectionUsageThreshold(); 988 MemoryUsage usage = pool.getUsage(); 989 long newT = newThreshold(usage, oldT, pool.getName()); 990 991 try { 992 pool.setCollectionUsageThreshold(newT); 993 } catch (IllegalArgumentException e) { 994 995 /* 996 * Max value might have changed since the call to newThreshold() 997 * above. If it has fallen below the value of newT, which is certainly 998 * possible, an exception like this one will be thrown from 999 * sun.management.MemoryPoolImpl.setCollectionUsageThreshold(): 1000 * 1001 * java.lang.IllegalArgumentException: Invalid threshold: 48332800 > max (47251456). 1002 * 1003 * We don't know the max value at the time of the failed call, and it 1004 * might have changed since the call once more. So there is no point 1005 * trying to detect whether the IllegalArgumentException had been 1006 * justified, we cannot know it at this point. 1007 * 1008 * The best we can do is log the fact and continue. 1009 */ 1010 displayInfo("setCollectionUsageThreshold() failed with " + e + ", ignoring... ", 1011 pool, 1012 "current usage after the call to setCollectionUsageThreshold(): ", getUsage(pool), 1013 "threshold: ", newT); 1014 continue; 1015 } 1016 displayInfo("Collection threshold is set", pool, "usage: ", getUsage(pool), "threshold: ", newT); 1017 if (pool.getCollectionUsageThreshold() != newT) { 1018 complain("Cannot reset collection threshold from " + oldT 1019 + " to " + newT + " in pool " + pool.getName() + " " 1020 + pool.getCollectionUsageThreshold()); 1021 passed = false; 1022 } 1023 } // for i 1024 break; 1025 1026 case SERVER_MODE: 1027 ObjectName[] pools = getMemoryPoolMXBeansOnServer(); 1028 1029 for (int i = 0; i < pools.length; i++) { 1030 if (!isCollectionThresholdSupportedOnServer(pools[i])) { 1031 continue; 1032 } 1033 1034 MemoryType mt = getType(pools[i]); 1035 if ((!mt.equals(MemoryType.HEAP) 1036 || !memory.equals(HEAP_TYPE)) 1037 && (!mt.equals(MemoryType.NON_HEAP) 1038 || !memory.equals(NONHEAP_TYPE)) 1039 && !memory.equals(MIXED_TYPE)) { 1040 continue; 1041 } 1042 1043 // Yes! We got the pool that 1044 // 1. supports usage threshold 1045 // 2. has type that match tested type 1046 // So, update the pool with new threshold 1047 long oldT = getCollectionThresholdOnServer(pools[i]); 1048 long newT = newThreshold(getUsageOnServer(pools[i]), oldT, 1049 pools[i].toString()); 1050 try { 1051 setCollectionThresholdOnServer(pools[i], newT); 1052 } catch (Failure e) { 1053 /* 1054 * Max value might have changed since the call to newThreshold() 1055 * above. If it has fallen below the value of newT, which is certainly 1056 * possible, an exception like this one will be thrown from 1057 * sun.management.MemoryPoolImpl.setCollectionUsageThreshold(): 1058 * 1059 * java.lang.IllegalArgumentException: Invalid threshold: 48332800 > max (47251456). 1060 * 1061 * and we'll catch Failure here as a result (it'll be thrown by 1062 * Monitor.setLongAttribute). 1063 * 1064 * We don't know the max value at the time of the failed call, and it 1065 * might have changed since the call once more. So there is no point 1066 * trying to detect whether the IllegalArgumentException had been 1067 * justified, we cannot know it at this point. 1068 * 1069 * The best we can do is log the fact and continue. 1070 */ 1071 displayInfo("setCollectionThresholdOnServer() failed with " + e + ", ignoring... ", 1072 pools[i], 1073 "current usage after the call to setCollectionThresholdOnServer(): ", getUsageOnServer(pools[i]), 1074 "threshold: ", newT); 1075 continue; 1076 } 1077 displayInfo("Collection threshold is set", pools[i], "usage: ", getUsageOnServer(pools[i]), "threshold: ", newT); 1078 if (getCollectionThresholdOnServer(pools[i]) != newT) { 1079 complain("Cannot reset collaction threshold from " + oldT 1080 + " to " + newT + " in pool " + pools[i].toString()); 1081 passed = false; 1082 } 1083 } // for i 1084 break; 1085 1086 default: 1087 throw new TestBug("Unknown testMode " + mode); 1088 } 1089 } // updateCollectionThresholds() 1090 1091 // Calculates a new value of threshold based on MemoryUsage and old value of 1092 // the threshold. New one will be not less than previous one. newThreshold(MemoryUsage mu, long oldT, String poolName)1093 private long newThreshold(MemoryUsage mu, long oldT, String poolName) { 1094 long newT = mu.getCommitted() / 2 + mu.getUsed() / 2; 1095 long max = mu.getMax(); 1096 1097 if (newT < oldT) { 1098 newT = mu.getCommitted() / 2 + oldT / 2; 1099 } 1100 if ((max > -1) && (newT > max)) { 1101 newT = max; 1102 } 1103 displayInfo("Changing threshold", poolName, null, null, "new threshold: ", newT); 1104 return newT; 1105 } 1106 1107 // ********************************************************************** 1108 // 1109 // Methods to work with MBean server in SERVER_MODE 1110 // 1111 // ********************************************************************** 1112 // Returns usage threshold value of the pool MBean that is accessed via 1113 // MBeanServer getUsageThresholdOnServer(ObjectName pool)1114 private long getUsageThresholdOnServer(ObjectName pool) { 1115 return getLongAttribute(pool, UT); 1116 } 1117 1118 // Returns collection threshold value of the pool MBean that is accessed via 1119 // MBeanServer getCollectionThresholdOnServer(ObjectName pool)1120 private long getCollectionThresholdOnServer(ObjectName pool) { 1121 return getLongAttribute(pool, CT); 1122 } 1123 1124 // Sets new usage threshold value for the pool MBean that is accessed via 1125 // MBeanServer setUsageThresholdOnServer(ObjectName pool, long value)1126 private void setUsageThresholdOnServer(ObjectName pool, long value) { 1127 setLongAttribute(pool, UT, value); 1128 } 1129 1130 // Sets new collection threshold value for the pool MBean that is accessed 1131 // via MBeanServer setCollectionThresholdOnServer(ObjectName pool, long value)1132 private void setCollectionThresholdOnServer(ObjectName pool, long value) { 1133 setLongAttribute(pool, CT, value); 1134 } 1135 1136 // Returns MemoryType of the pool MBean that is accessed via MBeanServer. getType(ObjectName pool)1137 private MemoryType getType(ObjectName pool) { 1138 try { 1139 Object value = getMBeanServer().getAttribute(pool, POOL_TYPE); 1140 if (value instanceof MemoryType) { 1141 return (MemoryType) value; 1142 } else if (value instanceof String) { 1143 String name = (String) value; 1144 return MemoryType.valueOf(name); 1145 } else { 1146 return null; 1147 } 1148 } catch (Exception e) { 1149 e.printStackTrace(logger.getOutStream()); 1150 throw new Failure(e); 1151 } 1152 } 1153 1154 // Returns MemoryUsage of the pool MBean that is accessed via MBeanServer getUsageOnServer(ObjectName pool)1155 private MemoryUsage getUsageOnServer(ObjectName pool) { 1156 return getMemoryUsageAttribute(pool, POOL_U); 1157 } 1158 1159 // Returns collection usage of the pool MBean that is accessed via 1160 // MBeanServer getCollectionUsageOnServer(ObjectName pool)1161 private MemoryUsage getCollectionUsageOnServer(ObjectName pool) { 1162 return getMemoryUsageAttribute(pool, POOL_CU); 1163 } 1164 1165 // Returns if usage threshold is supported in the pool isUsageThresholdSupportedOnServer(ObjectName pool)1166 private boolean isUsageThresholdSupportedOnServer(ObjectName pool) { 1167 return getBooleanAttribute(pool, UT_SUPPORT); 1168 } 1169 1170 // Returns if collection threshold is supported in the pool isCollectionThresholdSupportedOnServer(ObjectName pool)1171 private boolean isCollectionThresholdSupportedOnServer(ObjectName pool) { 1172 return getBooleanAttribute(pool, CT_SUPPORT); 1173 } 1174 1175 // Returns if usage threshold is exceeded in the pool isUsageThresholdExceededOnServer(ObjectName pool)1176 private boolean isUsageThresholdExceededOnServer(ObjectName pool) { 1177 return getBooleanAttribute(pool, UT_EXCEEDED); 1178 } 1179 1180 // Returns if collection threshold is exceeded in the pool isCollectionThresholdExceededOnServer(ObjectName pool)1181 private boolean isCollectionThresholdExceededOnServer(ObjectName pool) { 1182 return getBooleanAttribute(pool, CT_EXCEEDED); 1183 } 1184 1185 // Returns the usage threshold count of the pool getUsageThresholdCountOnServer(ObjectName pool)1186 private long getUsageThresholdCountOnServer(ObjectName pool) { 1187 return getLongAttribute(pool, UT_COUNT); 1188 } 1189 1190 // Returns the collection threshold count of the pool. getCollectionThresholdCountOnServer(ObjectName pool)1191 private long getCollectionThresholdCountOnServer(ObjectName pool) { 1192 return getLongAttribute(pool, CT_COUNT); 1193 } 1194 private final StringBuffer buffer = new StringBuffer(1000); 1195 1196 /** 1197 * Display information about execution ignoring OOM. 1198 */ displayInfo(String message, Object pool, String message1, Object n1, String message2, long n2)1199 private void displayInfo(String message, Object pool, String message1, Object n1, String message2, long n2) { 1200 try { 1201 buffer.delete(0, buffer.length()); 1202 buffer.append(message); 1203 if (pool != null) { 1204 buffer.append(", pool: "); 1205 buffer.append(pool.toString()); 1206 } 1207 buffer.append(", "); 1208 buffer.append(message1); 1209 buffer.append(n1); 1210 if (message2 != null) { 1211 buffer.append(", "); 1212 buffer.append(message2); 1213 buffer.append(n2); 1214 } 1215 display(buffer.toString()); 1216 } catch (OutOfMemoryError e) { 1217 // Ignore. 1218 } 1219 } 1220 1221 /** 1222 * Display information about execution ignoring OOM. 1223 */ displayInfo(String message, MemoryPoolMXBean pool, String message1, Object n1, String message2, Object n2)1224 private void displayInfo(String message, MemoryPoolMXBean pool, String message1, Object n1, String message2, Object n2) { 1225 try { 1226 buffer.delete(0, buffer.length()); 1227 buffer.append(message); 1228 if (pool != null) { 1229 buffer.append(", pool: "); 1230 buffer.append(pool.getName()); 1231 } 1232 buffer.append(", "); 1233 buffer.append(message1); 1234 buffer.append(n1); 1235 if (message2 != null) { 1236 buffer.append(", "); 1237 buffer.append(message2); 1238 buffer.append(n2); 1239 } 1240 display(buffer.toString()); 1241 } catch (OutOfMemoryError e) { 1242 // Ignore. 1243 } 1244 } 1245 1246 // Returns all MemoryPoolMXBeans that are registered on the MBeanServer getMemoryPoolMXBeansOnServer()1247 private ObjectName[] getMemoryPoolMXBeansOnServer() { 1248 1249 // Get all registered MBeans on the server 1250 ObjectName filterName = null; 1251 try { 1252 filterName = new ObjectName( 1253 ManagementFactory.MEMORY_POOL_MXBEAN_DOMAIN_TYPE + ",*"); 1254 1255 Set<ObjectName> filteredSet = getMBeanServer().queryNames(filterName, null); 1256 return filteredSet.toArray(new ObjectName[0]); 1257 } catch(Exception e) { 1258 return new ObjectName[0]; 1259 } 1260 1261 } // getMemoryPoolMXBeansOnServer() 1262 1263 // ********************************************************************** 1264 // 1265 // Class to implement polling mechanism of monitoring 1266 // 1267 // ********************************************************************** 1268 class Polling extends Thread { 1269 1270 final static long WAIT_TIME = 100; // Milliseconds 1271 Object object = new Object(); 1272 long[] thresholdCounts; 1273 boolean goOn = true; 1274 run()1275 public void run() { 1276 try { 1277 if (isUsageThreshold) { 1278 pollUsageThresholds(); 1279 } else { 1280 pollCollectionThresholds(); 1281 } 1282 } catch (Failure e) { 1283 complain("Unexpected " + e + " in Polling thread"); 1284 e.printStackTrace(logger.getOutStream()); 1285 passed = false; 1286 } 1287 } // run() 1288 pollUsageThresholds()1289 private void pollUsageThresholds() { 1290 switch (mode) { 1291 case DIRECTLY_MODE: 1292 // we can use the same code here for direct and proxy modes 1293 case PROXY_MODE: 1294 List poolsMBean = ManagementFactory.getMemoryPoolMXBeans(); 1295 1296 // Create an array to store all threshold values 1297 thresholdCounts = new long[poolsMBean.size()]; 1298 for (int i = 0; i < thresholdCounts.length; i++) { 1299 thresholdCounts[i] = 0; 1300 } 1301 1302 while (goOn) { 1303 synchronized (object) { 1304 try { 1305 object.wait(WAIT_TIME); 1306 } catch (InterruptedException e) { 1307 1308 // Stop the thread 1309 return; 1310 } 1311 } // synchronized 1312 1313 for (int i = 0; i < poolsMBean.size(); i++) { 1314 MemoryPoolMXBean pool = (MemoryPoolMXBean) poolsMBean.get(i); 1315 MemoryType mt = pool.getType(); 1316 1317 if (!pool.isUsageThresholdSupported()) { 1318 continue; 1319 } 1320 1321 if ((!mt.equals(MemoryType.HEAP) 1322 || !memory.equals(HEAP_TYPE)) 1323 && (!mt.equals(MemoryType.NON_HEAP) 1324 || !memory.equals(NONHEAP_TYPE)) 1325 && !memory.equals(MIXED_TYPE)) { 1326 continue; 1327 } 1328 1329 boolean exceeded; 1330 1331 // The exception is not documented, but it may be 1332 // erroneously thrown 1333 try { 1334 exceeded = pool.isUsageThresholdExceeded(); 1335 } catch (IllegalArgumentException e) { 1336 complain("Unexpected exception while retrieving " 1337 + "isUsageThresholdExceeded() for pool " 1338 + pool.getName()); 1339 e.printStackTrace(logger.getOutStream()); 1340 passed = false; 1341 continue; 1342 } 1343 1344 if (!exceeded 1345 || pool.getUsageThresholdCount() == thresholdCounts[i]) { 1346 continue; 1347 } 1348 1349 // Yes! We got the pool that 1350 // 1. supports usage threshold 1351 // 2. has type that match tested type 1352 // 3. its threshold is exceeded 1353 // So, update all thresholds 1354 long c = pool.getUsageThresholdCount(); 1355 if (c <= thresholdCounts[i]) { 1356 complain("Usage threshold count is not greater " 1357 + "than previous one: " + c + " < " 1358 + thresholdCounts[i] + " in pool " 1359 + pool.getName()); 1360 passed = false; 1361 } 1362 thresholdCounts[i] = c; 1363 displayInfo("Crossing is noticed", pool, "usage: ", pool.getUsage(), "count: ", c); 1364 updateThresholds(); 1365 } // for i 1366 } // while 1367 break; 1368 1369 case SERVER_MODE: 1370 ObjectName[] pools = getMemoryPoolMXBeansOnServer(); 1371 1372 // Create an array to store all threshold values 1373 thresholdCounts = new long[pools.length]; 1374 for (int i = 0; i < thresholdCounts.length; i++) { 1375 thresholdCounts[i] = 0; 1376 } 1377 1378 while (goOn) { 1379 synchronized (object) { 1380 try { 1381 object.wait(WAIT_TIME); 1382 } catch (InterruptedException e) { 1383 1384 // Stop the thread 1385 return; 1386 } 1387 } // synchronized 1388 1389 for (int i = 0; i < pools.length; i++) { 1390 MemoryType mt = getType(pools[i]); 1391 1392 if (!isUsageThresholdSupportedOnServer(pools[i])) { 1393 continue; 1394 } 1395 1396 if ((!mt.equals(MemoryType.HEAP) 1397 || !memory.equals(HEAP_TYPE)) 1398 && (!mt.equals(MemoryType.NON_HEAP) 1399 || !memory.equals(NONHEAP_TYPE)) 1400 && !memory.equals(MIXED_TYPE)) { 1401 continue; 1402 } 1403 1404 boolean exceeded; 1405 1406 // The exception is not documented, but it may be 1407 // erroneously thrown 1408 try { 1409 exceeded = isUsageThresholdExceededOnServer(pools[i]); 1410 } catch (Failure e) { 1411 complain("Unexpected exception while retrieving " 1412 + "isUsageThresholdExceeded() for pool " 1413 + pools[i].toString()); 1414 e.printStackTrace(logger.getOutStream()); 1415 passed = false; 1416 continue; 1417 } 1418 1419 if (!exceeded 1420 || getUsageThresholdCount(pools[i]) == thresholdCounts[i]) { 1421 continue; 1422 } 1423 1424 // Yes! We got the pool that 1425 // 1. supports usage threshold 1426 // 2. has type that match tested type 1427 // 3. its threshold is exceeded 1428 // So, update all thresholds 1429 long c = getUsageThresholdCount(pools[i]); 1430 if (c <= thresholdCounts[i]) { 1431 complain("Usage threshold count is not greater " 1432 + "than previous one: " + c + " < " 1433 + thresholdCounts[i] + " in pool " 1434 + pools[i].toString()); 1435 passed = false; 1436 } 1437 thresholdCounts[i] = c; 1438 displayInfo("Crossing is noticed", null, "pool: ", pools[i], "usage: ", getUsageOnServer(pools[i])); 1439 updateThresholds(); 1440 } // for i 1441 } // while 1442 break; 1443 1444 default: 1445 throw new TestBug("Unknown testMode " + mode); 1446 } // switch 1447 } // pollUsageThresholds() 1448 pollCollectionThresholds()1449 private void pollCollectionThresholds() { 1450 switch (mode) { 1451 case DIRECTLY_MODE: 1452 // we can use the same code here for direct and proxy modes 1453 case PROXY_MODE: 1454 List poolsMBean = ManagementFactory.getMemoryPoolMXBeans(); 1455 1456 // Create an array to store all threshold values 1457 thresholdCounts = new long[poolsMBean.size()]; 1458 for (int i = 0; i < thresholdCounts.length; i++) { 1459 thresholdCounts[i] = 0; 1460 } 1461 1462 while (goOn) { 1463 synchronized (object) { 1464 try { 1465 object.wait(WAIT_TIME); 1466 } catch (InterruptedException e) { 1467 1468 // Stop the thread 1469 return; 1470 } 1471 } // synchronized 1472 1473 for (int i = 0; i < poolsMBean.size(); i++) { 1474 MemoryPoolMXBean pool = (MemoryPoolMXBean) poolsMBean.get(i); 1475 MemoryType mt = pool.getType(); 1476 1477 if (!pool.isCollectionUsageThresholdSupported()) { 1478 continue; 1479 } 1480 1481 if ((!mt.equals(MemoryType.HEAP) 1482 || !memory.equals(HEAP_TYPE)) 1483 && (!mt.equals(MemoryType.NON_HEAP) 1484 || !memory.equals(NONHEAP_TYPE)) 1485 && !memory.equals(MIXED_TYPE)) { 1486 continue; 1487 } 1488 1489 boolean exceeded; 1490 1491 // The exception is not documented, but it may be 1492 // erroneously thrown 1493 try { 1494 exceeded = pool.isCollectionUsageThresholdExceeded(); 1495 } catch (IllegalArgumentException e) { 1496 complain("Unexpected exception while retrieving " 1497 + "isCollectionUsageThresholdExceeded()" 1498 + " for pool " + pool.getName()); 1499 e.printStackTrace(logger.getOutStream()); 1500 passed = false; 1501 continue; 1502 } 1503 1504 if (!exceeded 1505 || pool.getCollectionUsageThresholdCount() 1506 == thresholdCounts[i]) { 1507 continue; 1508 } 1509 1510 // Yes! We got thet pool that 1511 // 1. supports collection usage threshold 1512 // 2. has type that match tested type 1513 // 3. its threshold is exceeded 1514 // So, update all thresholds 1515 long c = pool.getCollectionUsageThresholdCount(); 1516 if (c <= thresholdCounts[i]) { 1517 complain("Collection usage threshold count is " 1518 + "not greater than previous one: " + c 1519 + " < " + thresholdCounts[i] + " in pool " 1520 + pool.getName()); 1521 passed = false; 1522 } 1523 thresholdCounts[i] = c; 1524 displayInfo("Crossing is noticed", pool, "usage: ", pool.getUsage(), "count: ", c); 1525 updateThresholds(); 1526 } // for i 1527 } // while 1528 break; 1529 1530 case SERVER_MODE: 1531 ObjectName[] pools = getMemoryPoolMXBeansOnServer(); 1532 1533 // Create an array to store all threshold values 1534 thresholdCounts = new long[pools.length]; 1535 for (int i = 0; i < thresholdCounts.length; i++) { 1536 thresholdCounts[i] = 0; 1537 } 1538 1539 while (goOn) { 1540 synchronized (object) { 1541 try { 1542 object.wait(WAIT_TIME); 1543 } catch (InterruptedException e) { 1544 1545 // Stop the thread 1546 return; 1547 } 1548 } // synchronized 1549 1550 for (int i = 0; i < pools.length; i++) { 1551 MemoryType mt = getType(pools[i]); 1552 1553 if (!isCollectionThresholdSupportedOnServer(pools[i])) { 1554 continue; 1555 } 1556 1557 if ((!mt.equals(MemoryType.HEAP) 1558 || !memory.equals(HEAP_TYPE)) 1559 && (!mt.equals(MemoryType.NON_HEAP) 1560 || !memory.equals(NONHEAP_TYPE)) 1561 && !memory.equals(MIXED_TYPE)) { 1562 continue; 1563 } 1564 1565 boolean exceeded; 1566 1567 // The exception is not documented, but it may be 1568 // erroneously thrown 1569 try { 1570 exceeded = isCollectionThresholdExceededOnServer(pools[i]); 1571 } catch (Failure e) { 1572 complain("Unexpected exception while retrieving " 1573 + "isCollectionUsageThresholdExceeded() " 1574 + "for pool " + pools[i].toString()); 1575 e.printStackTrace(logger.getOutStream()); 1576 passed = false; 1577 continue; 1578 } 1579 1580 if (!exceeded 1581 || getCollectionThresholdCountOnServer(pools[i]) 1582 == thresholdCounts[i]) { 1583 continue; 1584 } 1585 1586 // Yes! We got thet pool that 1587 // 1. supports collection usage threshold 1588 // 2. has type that match tested type 1589 // 3. its threshold is exceeded 1590 // So, update all thresholds 1591 long c = getCollectionThresholdCountOnServer(pools[i]); 1592 if (c <= thresholdCounts[i]) { 1593 complain("Collection usage threshold count is " 1594 + "not greater than previous one: " + c 1595 + " < " + thresholdCounts[i] + " in pool " 1596 + pools[i].toString()); 1597 passed = false; 1598 } 1599 thresholdCounts[i] = c; 1600 displayInfo("Crossing is noticed", pools[i], "usage: ", getUsageOnServer(pools[i]), "count: ", c); 1601 updateThresholds(); 1602 } // for i 1603 } // while 1604 break; 1605 1606 default: 1607 throw new TestBug("Unknown testMode " + mode); 1608 } // switch 1609 } // pollCollectionThresholds() 1610 } // class Polling 1611 } // MemoryMonitor 1612