001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.pool2.impl; 018 019import java.io.PrintWriter; 020import java.io.StringWriter; 021import java.io.Writer; 022import java.lang.management.ManagementFactory; 023import java.util.ArrayList; 024import java.util.Iterator; 025import java.util.LinkedList; 026import java.util.List; 027import java.util.TimerTask; 028import java.util.concurrent.atomic.AtomicLong; 029 030import javax.management.InstanceAlreadyExistsException; 031import javax.management.InstanceNotFoundException; 032import javax.management.MBeanRegistrationException; 033import javax.management.MBeanServer; 034import javax.management.MalformedObjectNameException; 035import javax.management.NotCompliantMBeanException; 036import javax.management.ObjectName; 037 038import org.apache.commons.pool2.PooledObject; 039import org.apache.commons.pool2.SwallowedExceptionListener; 040 041/** 042 * Base class that provides common functionality for {@link GenericObjectPool} 043 * and {@link GenericKeyedObjectPool}. The primary reason this class exists is 044 * reduce code duplication between the two pool implementations. 045 * 046 * @param <T> Type of element pooled in this pool. 047 * 048 * This class is intended to be thread-safe. 049 * 050 * @version $Revision: $ 051 * 052 * @since 2.0 053 */ 054public abstract class BaseGenericObjectPool<T> { 055 056 // Constants 057 /** 058 * The size of the caches used to store historical data for some attributes 059 * so that rolling means may be calculated. 060 */ 061 public static final int MEAN_TIMING_STATS_CACHE_SIZE = 100; 062 063 // Configuration attributes 064 private volatile int maxTotal = 065 GenericKeyedObjectPoolConfig.DEFAULT_MAX_TOTAL; 066 private volatile boolean blockWhenExhausted = 067 BaseObjectPoolConfig.DEFAULT_BLOCK_WHEN_EXHAUSTED; 068 private volatile long maxWaitMillis = 069 BaseObjectPoolConfig.DEFAULT_MAX_WAIT_MILLIS; 070 private volatile boolean lifo = BaseObjectPoolConfig.DEFAULT_LIFO; 071 private volatile boolean testOnBorrow = 072 BaseObjectPoolConfig.DEFAULT_TEST_ON_BORROW; 073 private volatile boolean testOnReturn = 074 BaseObjectPoolConfig.DEFAULT_TEST_ON_RETURN; 075 private volatile boolean testWhileIdle = 076 BaseObjectPoolConfig.DEFAULT_TEST_WHILE_IDLE; 077 private volatile long timeBetweenEvictionRunsMillis = 078 BaseObjectPoolConfig.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS; 079 private volatile int numTestsPerEvictionRun = 080 BaseObjectPoolConfig.DEFAULT_NUM_TESTS_PER_EVICTION_RUN; 081 private volatile long minEvictableIdleTimeMillis = 082 BaseObjectPoolConfig.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS; 083 private volatile long softMinEvictableIdleTimeMillis = 084 BaseObjectPoolConfig.DEFAULT_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS; 085 private volatile EvictionPolicy<T> evictionPolicy; 086 087 088 // Internal (primarily state) attributes 089 final Object closeLock = new Object(); 090 volatile boolean closed = false; 091 final Object evictionLock = new Object(); 092 private Evictor evictor = null; // @GuardedBy("evictionLock") 093 Iterator<PooledObject<T>> evictionIterator = null; // @GuardedBy("evictionLock") 094 /* 095 * Class loader for evictor thread to use since in a J2EE or similar 096 * environment the context class loader for the evictor thread may have 097 * visibility of the correct factory. See POOL-161. 098 */ 099 private final ClassLoader factoryClassLoader; 100 101 102 // Monitoring (primarily JMX) attributes 103 private final ObjectName oname; 104 private final String creationStackTrace; 105 private final AtomicLong borrowedCount = new AtomicLong(0); 106 private final AtomicLong returnedCount = new AtomicLong(0); 107 final AtomicLong createdCount = new AtomicLong(0); 108 final AtomicLong destroyedCount = new AtomicLong(0); 109 final AtomicLong destroyedByEvictorCount = new AtomicLong(0); 110 final AtomicLong destroyedByBorrowValidationCount = new AtomicLong(0); 111 private final LinkedList<Long> activeTimes = new LinkedList<Long>(); // @GuardedBy("activeTimes") - except in initStats() 112 private final LinkedList<Long> idleTimes = new LinkedList<Long>(); // @GuardedBy("activeTimes") - except in initStats() 113 private final LinkedList<Long> waitTimes = new LinkedList<Long>(); // @GuardedBy("activeTimes") - except in initStats() 114 private final Object maxBorrowWaitTimeMillisLock = new Object(); 115 private volatile long maxBorrowWaitTimeMillis = 0; // @GuardedBy("maxBorrowWaitTimeMillisLock") 116 private SwallowedExceptionListener swallowedExceptionListener = null; 117 118 119 /** 120 * Handles JMX registration (if required) and the initialization required for 121 * monitoring. 122 * 123 * @param config Pool configuration 124 * @param jmxNameBase The default base JMX name for the new pool unless 125 * overridden by the config 126 * @param jmxNamePrefix Prefix to be used for JMX name for the new pool 127 */ 128 public BaseGenericObjectPool(BaseObjectPoolConfig config, 129 String jmxNameBase, String jmxNamePrefix) { 130 if (config.getJmxEnabled()) { 131 this.oname = jmxRegister(config, jmxNameBase, jmxNamePrefix); 132 } else { 133 this.oname = null; 134 } 135 136 // Populate the creation stack trace 137 this.creationStackTrace = getStackTrace(new Exception()); 138 139 // save the current CCL to be used later by the evictor Thread 140 factoryClassLoader = Thread.currentThread().getContextClassLoader(); 141 142 // Initialise the attributes used to record rolling averages 143 initStats(); 144 } 145 146 147 /** 148 * Returns the maximum number of objects that can be allocated by the pool 149 * (checked out to clients, or idle awaiting checkout) at a given time. When 150 * negative, there is no limit to the number of objects that can be 151 * managed by the pool at one time. 152 * 153 * @return the cap on the total number of object instances managed by the 154 * pool. 155 * 156 * @see #setMaxTotal 157 */ 158 public final int getMaxTotal() { 159 return maxTotal; 160 } 161 162 /** 163 * Sets the cap on the number of objects that can be allocated by the pool 164 * (checked out to clients, or idle awaiting checkout) at a given time. Use 165 * a negative value for no limit. 166 * 167 * @param maxTotal The cap on the total number of object instances managed 168 * by the pool. Negative values mean that there is no limit 169 * to the number of objects allocated by the pool. 170 * 171 * @see #getMaxTotal 172 */ 173 public final void setMaxTotal(int maxTotal) { 174 this.maxTotal = maxTotal; 175 } 176 177 /** 178 * Returns whether to block when the <code>borrowObject()</code> method is 179 * invoked when the pool is exhausted (the maximum number of "active" 180 * objects has been reached). 181 * 182 * @return <code>true</code> if <code>borrowObject()</code> should block 183 * when the pool is exhausted 184 * 185 * @see #setBlockWhenExhausted 186 */ 187 public final boolean getBlockWhenExhausted() { 188 return blockWhenExhausted; 189 } 190 191 /** 192 * Sets whether to block when the <code>borrowObject()</code> method is 193 * invoked when the pool is exhausted (the maximum number of "active" 194 * objects has been reached). 195 * 196 * @param blockWhenExhausted <code>true</code> if 197 * <code>borrowObject()</code> should block 198 * when the pool is exhausted 199 * 200 * @see #getBlockWhenExhausted 201 */ 202 public final void setBlockWhenExhausted(boolean blockWhenExhausted) { 203 this.blockWhenExhausted = blockWhenExhausted; 204 } 205 206 /** 207 * Returns the maximum amount of time (in milliseconds) the 208 * <code>borrowObject()</code> method should block before throwing an 209 * exception when the pool is exhausted and 210 * {@link #getBlockWhenExhausted} is true. When less than 0, the 211 * <code>borrowObject()</code> method may block indefinitely. 212 * 213 * @return the maximum number of milliseconds <code>borrowObject()</code> 214 * will block. 215 * 216 * @see #setMaxWaitMillis 217 * @see #setBlockWhenExhausted 218 */ 219 public final long getMaxWaitMillis() { 220 return maxWaitMillis; 221 } 222 223 /** 224 * Sets the maximum amount of time (in milliseconds) the 225 * <code>borrowObject()</code> method should block before throwing an 226 * exception when the pool is exhausted and 227 * {@link #getBlockWhenExhausted} is true. When less than 0, the 228 * <code>borrowObject()</code> method may block indefinitely. 229 * 230 * @param maxWaitMillis the maximum number of milliseconds 231 * <code>borrowObject()</code> will block or negative 232 * for indefinitely. 233 * 234 * @see #getMaxWaitMillis 235 * @see #setBlockWhenExhausted 236 */ 237 public final void setMaxWaitMillis(long maxWaitMillis) { 238 this.maxWaitMillis = maxWaitMillis; 239 } 240 241 /** 242 * Returns whether the pool has LIFO (last in, first out) behaviour with 243 * respect to idle objects - always returning the most recently used object 244 * from the pool, or as a FIFO (first in, first out) queue, where the pool 245 * always returns the oldest object in the idle object pool. 246 * 247 * @return <code>true</code> if the pool is configured with LIFO behaviour 248 * or <code>false</code> if the pool is configured with FIFO 249 * behaviour 250 * 251 * @see #setLifo 252 */ 253 public final boolean getLifo() { 254 return lifo; 255 } 256 257 /** 258 * Sets whether the pool has LIFO (last in, first out) behaviour with 259 * respect to idle objects - always returning the most recently used object 260 * from the pool, or as a FIFO (first in, first out) queue, where the pool 261 * always returns the oldest object in the idle object pool. 262 * 263 * @param lifo <code>true</code> if the pool is to be configured with LIFO 264 * behaviour or <code>false</code> if the pool is to be 265 * configured with FIFO behaviour 266 * 267 * @see #getLifo() 268 */ 269 public final void setLifo(boolean lifo) { 270 this.lifo = lifo; 271 } 272 273 /** 274 * Returns whether objects borrowed from the pool will be validated before 275 * being returned from the <code>borrowObject()</code> method. Validation is 276 * performed by the <code>validateObject()</code> method of the factory 277 * associated with the pool. If the object fails to validate, it will be 278 * removed from the pool and destroyed, and a new attempt will be made to 279 * borrow an object from the pool. 280 * 281 * @return <code>true</code> if objects are validated before being returned 282 * from the <code>borrowObject()</code> method 283 * 284 * @see #setTestOnBorrow 285 */ 286 public final boolean getTestOnBorrow() { 287 return testOnBorrow; 288 } 289 290 /** 291 * Sets whether objects borrowed from the pool will be validated before 292 * being returned from the <code>borrowObject()</code> method. Validation is 293 * performed by the <code>validateObject()</code> method of the factory 294 * associated with the pool. If the object fails to validate, it will be 295 * removed from the pool and destroyed, and a new attempt will be made to 296 * borrow an object from the pool. 297 * 298 * @param testOnBorrow <code>true</code> if objects should be validated 299 * before being returned from the 300 * <code>borrowObject()</code> method 301 * 302 * @see #getTestOnBorrow 303 */ 304 public final void setTestOnBorrow(boolean testOnBorrow) { 305 this.testOnBorrow = testOnBorrow; 306 } 307 308 /** 309 * Returns whether objects borrowed from the pool will be validated when 310 * they are returned to the pool via the <code>returnObject()</code> method. 311 * Validation is performed by the <code>validateObject()</code> method of 312 * the factory associated with the pool. Returning objects that fail validation 313 * are destroyed rather then being returned the pool. 314 * 315 * @return <code>true</code> if objects are validated on return to 316 * the pool via the <code>returnObject()</code> method 317 * 318 * @see #setTestOnReturn 319 */ 320 public final boolean getTestOnReturn() { 321 return testOnReturn; 322 } 323 324 /** 325 * Sets whether objects borrowed from the pool will be validated when 326 * they are returned to the pool via the <code>returnObject()</code> method. 327 * Validation is performed by the <code>validateObject()</code> method of 328 * the factory associated with the pool. Returning objects that fail validation 329 * are destroyed rather then being returned the pool. 330 * 331 * @param testOnReturn <code>true</code> if objects are validated on 332 * return to the pool via the 333 * <code>returnObject()</code> method 334 * 335 * @see #getTestOnReturn 336 */ 337 public final void setTestOnReturn(boolean testOnReturn) { 338 this.testOnReturn = testOnReturn; 339 } 340 341 /** 342 * Returns whether objects sitting idle in the pool will be validated by the 343 * idle object evictor (if any - see 344 * {@link #setTimeBetweenEvictionRunsMillis(long)}). Validation is performed 345 * by the <code>validateObject()</code> method of the factory associated 346 * with the pool. If the object fails to validate, it will be removed from 347 * the pool and destroyed. 348 * 349 * @return <code>true</code> if objects will be validated by the evictor 350 * 351 * @see #setTestWhileIdle 352 * @see #setTimeBetweenEvictionRunsMillis 353 */ 354 public final boolean getTestWhileIdle() { 355 return testWhileIdle; 356 } 357 358 /** 359 * Returns whether objects sitting idle in the pool will be validated by the 360 * idle object evictor (if any - see 361 * {@link #setTimeBetweenEvictionRunsMillis(long)}). Validation is performed 362 * by the <code>validateObject()</code> method of the factory associated 363 * with the pool. If the object fails to validate, it will be removed from 364 * the pool and destroyed. Note that setting this property has no effect 365 * unless the idle object evictor is enabled by setting 366 * <code>timeBetweenEvictionRunsMillis</code> to a positive value. 367 * 368 * @param testWhileIdle 369 * <code>true</code> so objects will be validated by the evictor 370 * 371 * @see #getTestWhileIdle 372 * @see #setTimeBetweenEvictionRunsMillis 373 */ 374 public final void setTestWhileIdle(boolean testWhileIdle) { 375 this.testWhileIdle = testWhileIdle; 376 } 377 378 /** 379 * Returns the number of milliseconds to sleep between runs of the idle 380 * object evictor thread. When non-positive, no idle object evictor thread 381 * will be run. 382 * 383 * @return number of milliseconds to sleep between evictor runs 384 * 385 * @see #setTimeBetweenEvictionRunsMillis 386 */ 387 public final long getTimeBetweenEvictionRunsMillis() { 388 return timeBetweenEvictionRunsMillis; 389 } 390 391 /** 392 * Sets the number of milliseconds to sleep between runs of the idle 393 * object evictor thread. When non-positive, no idle object evictor thread 394 * will be run. 395 * 396 * @param timeBetweenEvictionRunsMillis 397 * number of milliseconds to sleep between evictor runs 398 * 399 * @see #getTimeBetweenEvictionRunsMillis 400 */ 401 public final void setTimeBetweenEvictionRunsMillis( 402 long timeBetweenEvictionRunsMillis) { 403 this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis; 404 startEvictor(timeBetweenEvictionRunsMillis); 405 } 406 407 /** 408 * Returns the maximum number of objects to examine during each run (if any) 409 * of the idle object evictor thread. When positive, the number of tests 410 * performed for a run will be the minimum of the configured value and the 411 * number of idle instances in the pool. When negative, the number of tests 412 * performed will be <code>ceil({@link #getNumIdle}/ 413 * abs({@link #getNumTestsPerEvictionRun})) which means that when the value 414 * is <code>-n</code> roughly one nth of the idle objects will be tested per 415 * run. 416 * 417 * @return max number of objects to examine during each evictor run 418 * 419 * @see #setNumTestsPerEvictionRun 420 * @see #setTimeBetweenEvictionRunsMillis 421 */ 422 public final int getNumTestsPerEvictionRun() { 423 return numTestsPerEvictionRun; 424 } 425 426 /** 427 * Sets the maximum number of objects to examine during each run (if any) 428 * of the idle object evictor thread. When positive, the number of tests 429 * performed for a run will be the minimum of the configured value and the 430 * number of idle instances in the pool. When negative, the number of tests 431 * performed will be <code>ceil({@link #getNumIdle}/ 432 * abs({@link #getNumTestsPerEvictionRun})) which means that when the value 433 * is <code>-n</code> roughly one nth of the idle objects will be tested per 434 * run. 435 * 436 * @param numTestsPerEvictionRun 437 * max number of objects to examine during each evictor run 438 * 439 * @see #getNumTestsPerEvictionRun 440 * @see #setTimeBetweenEvictionRunsMillis 441 */ 442 public final void setNumTestsPerEvictionRun(int numTestsPerEvictionRun) { 443 this.numTestsPerEvictionRun = numTestsPerEvictionRun; 444 } 445 446 /** 447 * Returns the minimum amount of time an object may sit idle in the pool 448 * before it is eligible for eviction by the idle object evictor (if any - 449 * see {@link #setTimeBetweenEvictionRunsMillis(long)}). When non-positive, 450 * no objects will be evicted from the pool due to idle time alone. 451 * 452 * @return minimum amount of time an object may sit idle in the pool before 453 * it is eligible for eviction 454 * 455 * @see #setMinEvictableIdleTimeMillis 456 * @see #setTimeBetweenEvictionRunsMillis 457 */ 458 public final long getMinEvictableIdleTimeMillis() { 459 return minEvictableIdleTimeMillis; 460 } 461 462 /** 463 * Sets the minimum amount of time an object may sit idle in the pool 464 * before it is eligible for eviction by the idle object evictor (if any - 465 * see {@link #setTimeBetweenEvictionRunsMillis(long)}). When non-positive, 466 * no objects will be evicted from the pool due to idle time alone. 467 * 468 * @param minEvictableIdleTimeMillis 469 * minimum amount of time an object may sit idle in the pool 470 * before it is eligible for eviction 471 * 472 * @see #getMinEvictableIdleTimeMillis 473 * @see #setTimeBetweenEvictionRunsMillis 474 */ 475 public final void setMinEvictableIdleTimeMillis( 476 long minEvictableIdleTimeMillis) { 477 this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis; 478 } 479 480 /** 481 * Returns the minimum amount of time an object may sit idle in the pool 482 * before it is eligible for eviction by the idle object evictor (if any - 483 * see {@link #setTimeBetweenEvictionRunsMillis(long)}), 484 * with the extra condition that at least <code>minIdle</code> object 485 * instances remain in the pool. This setting is overridden by 486 * {@link #getMinEvictableIdleTimeMillis} (that is, if 487 * {@link #getMinEvictableIdleTimeMillis} is positive, then 488 * {@link #getSoftMinEvictableIdleTimeMillis} is ignored). 489 * 490 * @return minimum amount of time an object may sit idle in the pool before 491 * it is eligible for eviction if minIdle instances are available 492 * 493 * @see #setSoftMinEvictableIdleTimeMillis 494 */ 495 public final long getSoftMinEvictableIdleTimeMillis() { 496 return softMinEvictableIdleTimeMillis; 497 } 498 499 /** 500 * Sets the minimum amount of time an object may sit idle in the pool 501 * before it is eligible for eviction by the idle object evictor (if any - 502 * see {@link #setTimeBetweenEvictionRunsMillis(long)}), 503 * with the extra condition that at least <code>minIdle</code> object 504 * instances remain in the pool. This setting is overridden by 505 * {@link #getMinEvictableIdleTimeMillis} (that is, if 506 * {@link #getMinEvictableIdleTimeMillis} is positive, then 507 * {@link #getSoftMinEvictableIdleTimeMillis} is ignored). 508 * 509 * @param softMinEvictableIdleTimeMillis 510 * minimum amount of time an object may sit idle in the pool 511 * before it is eligible for eviction if minIdle instances are 512 * available 513 * 514 * @see #getSoftMinEvictableIdleTimeMillis 515 */ 516 public final void setSoftMinEvictableIdleTimeMillis( 517 long softMinEvictableIdleTimeMillis) { 518 this.softMinEvictableIdleTimeMillis = softMinEvictableIdleTimeMillis; 519 } 520 521 /** 522 * Returns the name of the {@link EvictionPolicy} implementation that is 523 * used by this pool. 524 * 525 * @return The fully qualified class name of the {@link EvictionPolicy} 526 * 527 * @see #setEvictionPolicyClassName(String) 528 */ 529 public final String getEvictionPolicyClassName() { 530 return evictionPolicy.getClass().getName(); 531 } 532 533 /** 534 * Sets the name of the {@link EvictionPolicy} implementation that is 535 * used by this pool. 536 * 537 * @param evictionPolicyClassName the fully qualified class name of the 538 * new eviction policy 539 * 540 * @see #getEvictionPolicyClassName() 541 */ 542 public final void setEvictionPolicyClassName( 543 String evictionPolicyClassName) { 544 try { 545 Class<?> clazz = Class.forName(evictionPolicyClassName); 546 Object policy = clazz.newInstance(); 547 if (policy instanceof EvictionPolicy<?>) { 548 @SuppressWarnings("unchecked") // safe, because we just checked the class 549 EvictionPolicy<T> evicPolicy = (EvictionPolicy<T>) policy; 550 this.evictionPolicy = evicPolicy; 551 } 552 } catch (ClassNotFoundException e) { 553 throw new IllegalArgumentException( 554 "Unable to create EvictionPolicy instance of type " + 555 evictionPolicyClassName, e); 556 } catch (InstantiationException e) { 557 throw new IllegalArgumentException( 558 "Unable to create EvictionPolicy instance of type " + 559 evictionPolicyClassName, e); 560 } catch (IllegalAccessException e) { 561 throw new IllegalArgumentException( 562 "Unable to create EvictionPolicy instance of type " + 563 evictionPolicyClassName, e); 564 } 565 } 566 567 568 /** 569 * Closes the pool, destroys the remaining idle objects and, if registered 570 * in JMX, deregisters it. 571 */ 572 public abstract void close(); 573 574 /** 575 * Has this pool instance been closed. 576 * @return <code>true</code> when this pool has been closed. 577 */ 578 public final boolean isClosed() { 579 return closed; 580 } 581 582 /** 583 * <p>Perform <code>numTests</code> idle object eviction tests, evicting 584 * examined objects that meet the criteria for eviction. If 585 * <code>testWhileIdle</code> is true, examined objects are validated 586 * when visited (and removed if invalid); otherwise only objects that 587 * have been idle for more than <code>minEvicableIdleTimeMillis</code> 588 * are removed.</p> 589 * 590 * @throws Exception when there is a problem evicting idle objects. 591 */ 592 public abstract void evict() throws Exception; 593 594 /** 595 * Returns the {@link EvictionPolicy} defined for this pool. 596 * @return the eviction policy 597 */ 598 final EvictionPolicy<T> getEvictionPolicy() { 599 return evictionPolicy; 600 } 601 602 /** 603 * Verifies that the pool is open. 604 * @throws IllegalStateException if the pool is closed. 605 */ 606 final void assertOpen() throws IllegalStateException { 607 if (isClosed()) { 608 throw new IllegalStateException("Pool not open"); 609 } 610 } 611 612 /** 613 * <p>Starts the evictor with the given delay. If there is an evictor 614 * running when this method is called, it is stopped and replaced with a 615 * new evictor with the specified delay.</p> 616 * 617 * <p>This method needs to be final, since it is called from a constructor. 618 * See POOL-195.</p> 619 * 620 * @param delay time in milliseconds before start and between eviction runs 621 */ 622 final void startEvictor(long delay) { 623 synchronized (evictionLock) { 624 if (null != evictor) { 625 EvictionTimer.cancel(evictor); 626 evictor = null; 627 evictionIterator = null; 628 } 629 if (delay > 0) { 630 evictor = new Evictor(); 631 EvictionTimer.schedule(evictor, delay, delay); 632 } 633 } 634 } 635 636 /** 637 * Tries to ensure that the configured minimum number of idle instances are 638 * available in the pool. 639 * @throws Exception if an error occurs creating idle instances 640 */ 641 abstract void ensureMinIdle() throws Exception; 642 643 644 // Monitoring (primarily JMX) related methods 645 646 /** 647 * Provides the name under which the pool has been registered with the 648 * platform MBean server or <code>null</code> if the pool has not been 649 * registered. 650 * @return the JMX name 651 */ 652 public final ObjectName getJmxName() { 653 return oname; 654 } 655 656 /** 657 * Provides the stack trace for the call that created this pool. JMX 658 * registration may trigger a memory leak so it is important that pools are 659 * deregistered when no longer used by calling the {@link #close()} method. 660 * This method is provided to assist with identifying code that creates but 661 * does not close it thereby creating a memory leak. 662 * @return pool creation stack trace 663 */ 664 public final String getCreationStackTrace() { 665 return creationStackTrace; 666 } 667 668 /** 669 * The total number of objects successfully borrowed from this pool over the 670 * lifetime of the pool. 671 * @return the borrowed object count 672 */ 673 public final long getBorrowedCount() { 674 return borrowedCount.get(); 675 } 676 677 /** 678 * The total number of objects returned to this pool over the lifetime of 679 * the pool. This excludes attempts to return the same object multiple 680 * times. 681 * @return the returned object count 682 */ 683 public final long getReturnedCount() { 684 return returnedCount.get(); 685 } 686 687 /** 688 * The total number of objects created for this pool over the lifetime of 689 * the pool. 690 * @return the created object count 691 */ 692 public final long getCreatedCount() { 693 return createdCount.get(); 694 } 695 696 /** 697 * The total number of objects destroyed by this pool over the lifetime of 698 * the pool. 699 * @return the destroyed object count 700 */ 701 public final long getDestroyedCount() { 702 return destroyedCount.get(); 703 } 704 705 /** 706 * The total number of objects destroyed by the evictor associated with this 707 * pool over the lifetime of the pool. 708 * @return the evictor destroyed object count 709 */ 710 public final long getDestroyedByEvictorCount() { 711 return destroyedByEvictorCount.get(); 712 } 713 714 /** 715 * The total number of objects destroyed by this pool as a result of failing 716 * validation during <code>borrowObject()</code> over the lifetime of the 717 * pool. 718 * @return validation destroyed object count 719 */ 720 public final long getDestroyedByBorrowValidationCount() { 721 return destroyedByBorrowValidationCount.get(); 722 } 723 724 /** 725 * The mean time objects are active for based on the last {@link 726 * #MEAN_TIMING_STATS_CACHE_SIZE} objects returned to the pool. 727 * @return mean time an object has been checked out from the pool among 728 * recently returned objects 729 */ 730 public final long getMeanActiveTimeMillis() { 731 return getMeanFromStatsCache(activeTimes); 732 } 733 734 /** 735 * The mean time objects are idle for based on the last {@link 736 * #MEAN_TIMING_STATS_CACHE_SIZE} objects borrowed from the pool. 737 * @return mean time an object has been idle in the pool among recently 738 * borrowed objects 739 */ 740 public final long getMeanIdleTimeMillis() { 741 return getMeanFromStatsCache(idleTimes); 742 } 743 744 /** 745 * The mean time threads wait to borrow an object based on the last {@link 746 * #MEAN_TIMING_STATS_CACHE_SIZE} objects borrowed from the pool. 747 * @return mean time in milliseconds that a recently served thread has had 748 * to wait to borrow an object from the pool 749 */ 750 public final long getMeanBorrowWaitTimeMillis() { 751 return getMeanFromStatsCache(waitTimes); 752 } 753 754 /** 755 * The maximum time a thread has waited to borrow objects from the pool. 756 * @return maximum wait time in milliseconds since the pool was created 757 */ 758 public final long getMaxBorrowWaitTimeMillis() { 759 return maxBorrowWaitTimeMillis; 760 } 761 762 /** 763 * The number of instances currently idle in this pool. 764 * @return count of instances available for checkout from the pool 765 */ 766 public abstract int getNumIdle(); 767 768 /** 769 * The listener used (if any) to receive notifications of exceptions 770 * unavoidably swallowed by the pool. 771 * 772 * @return The listener or <code>null</code> for no listener 773 */ 774 public final SwallowedExceptionListener getSwallowedExceptionListener() { 775 return swallowedExceptionListener; 776 } 777 778 /** 779 * The listener used (if any) to receive notifications of exceptions 780 * unavoidably swallowed by the pool. 781 * 782 * @param swallowedExceptionListener The listener or <code>null</code> 783 * for no listener 784 */ 785 public final void setSwallowedExceptionListener( 786 SwallowedExceptionListener swallowedExceptionListener) { 787 this.swallowedExceptionListener = swallowedExceptionListener; 788 } 789 790 /** 791 * Swallows an exception and notifies the configured listener for swallowed 792 * exceptions queue. 793 * 794 * @param e exception to be swallowed 795 */ 796 final void swallowException(Exception e) { 797 SwallowedExceptionListener listener = getSwallowedExceptionListener(); 798 799 if (listener == null) { 800 return; 801 } 802 803 try { 804 listener.onSwallowException(e); 805 } catch (OutOfMemoryError oome) { 806 throw oome; 807 } catch (VirtualMachineError vme) { 808 throw vme; 809 } catch (Throwable t) { 810 // Ignore. Enjoy the irony. 811 } 812 } 813 814 /** 815 * Updates statistics after an object is borrowed from the pool. 816 * @param p object borrowed from the pool 817 * @param waitTime time (in milliseconds) that the borrowing thread had to wait 818 */ 819 final void updateStatsBorrow(PooledObject<T> p, long waitTime) { 820 borrowedCount.incrementAndGet(); 821 synchronized (idleTimes) { 822 idleTimes.add(Long.valueOf(p.getIdleTimeMillis())); 823 idleTimes.poll(); 824 } 825 synchronized (waitTimes) { 826 waitTimes.add(Long.valueOf(waitTime)); 827 waitTimes.poll(); 828 } 829 synchronized (maxBorrowWaitTimeMillisLock) { 830 if (waitTime > maxBorrowWaitTimeMillis) { 831 maxBorrowWaitTimeMillis = waitTime; 832 } 833 } 834 } 835 836 /** 837 * Updates statistics after an object is returned to the pool. 838 * @param activeTime the amount of time (in milliseconds) that the returning 839 * object was checked out 840 */ 841 final void updateStatsReturn(long activeTime) { 842 returnedCount.incrementAndGet(); 843 synchronized (activeTimes) { 844 activeTimes.add(Long.valueOf(activeTime)); 845 activeTimes.poll(); 846 } 847 } 848 849 /** 850 * Unregisters this pool's MBean. 851 */ 852 final void jmxUnregister() { 853 if (oname != null) { 854 try { 855 ManagementFactory.getPlatformMBeanServer().unregisterMBean( 856 oname); 857 } catch (MBeanRegistrationException e) { 858 swallowException(e); 859 } catch (InstanceNotFoundException e) { 860 swallowException(e); 861 } 862 } 863 } 864 865 /** 866 * Registers the pool with the platform MBean server. 867 * The registered name will be 868 * <code>jmxNameBase + jmxNamePrefix + i</code> where i is the least 869 * integer greater than or equal to 1 such that the name is not already 870 * registered. Swallows MBeanRegistrationException, NotCompliantMBeanException 871 * returning null. 872 * 873 * @param config Pool configuration 874 * @param jmxNameBase default base JMX name for this pool 875 * @param jmxNamePrefix name prefix 876 * @return registered ObjectName, null if registration fails 877 */ 878 private ObjectName jmxRegister(BaseObjectPoolConfig config, 879 String jmxNameBase, String jmxNamePrefix) { 880 ObjectName objectName = null; 881 MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); 882 int i = 1; 883 boolean registered = false; 884 String base = config.getJmxNameBase(); 885 if (base == null) { 886 base = jmxNameBase; 887 } 888 while (!registered) { 889 try { 890 ObjectName objName; 891 // Skip the numeric suffix for the first pool in case there is 892 // only one so the names are cleaner. 893 if (i == 1) { 894 objName = new ObjectName(base + jmxNamePrefix); 895 } else { 896 objName = new ObjectName(base + jmxNamePrefix + i); 897 } 898 mbs.registerMBean(this, objName); 899 objectName = objName; 900 registered = true; 901 } catch (MalformedObjectNameException e) { 902 if (BaseObjectPoolConfig.DEFAULT_JMX_NAME_PREFIX.equals( 903 jmxNamePrefix) && jmxNameBase.equals(base)) { 904 // Shouldn't happen. Skip registration if it does. 905 registered = true; 906 } else { 907 // Must be an invalid name. Use the defaults instead. 908 jmxNamePrefix = 909 BaseObjectPoolConfig.DEFAULT_JMX_NAME_PREFIX; 910 base = jmxNameBase; 911 } 912 } catch (InstanceAlreadyExistsException e) { 913 // Increment the index and try again 914 i++; 915 } catch (MBeanRegistrationException e) { 916 // Shouldn't happen. Skip registration if it does. 917 registered = true; 918 } catch (NotCompliantMBeanException e) { 919 // Shouldn't happen. Skip registration if it does. 920 registered = true; 921 } 922 } 923 return objectName; 924 } 925 926 /** 927 * Gets the stack trace of an exception as a string. 928 * @param e exception to trace 929 * @return exception stack trace as a string 930 */ 931 private String getStackTrace(Exception e) { 932 // Need the exception in string form to prevent the retention of 933 // references to classes in the stack trace that could trigger a memory 934 // leak in a container environment. 935 Writer w = new StringWriter(); 936 PrintWriter pw = new PrintWriter(w); 937 e.printStackTrace(pw); 938 return w.toString(); 939 } 940 941 /** 942 * Returns the greatest integer less than ore equal to the arithmetic mean 943 * of the entries in <code>cache,</code> acquiring and holding the argument's 944 * monitor while making a local copy. 945 * @param cache list containing entries to analyze 946 * @return truncated arithmetic mean 947 */ 948 private long getMeanFromStatsCache(LinkedList<Long> cache) { 949 List<Long> times = new ArrayList<Long>(MEAN_TIMING_STATS_CACHE_SIZE); 950 synchronized (cache) { 951 times.addAll(cache); 952 } 953 double result = 0; 954 int counter = 0; 955 Iterator<Long> iter = times.iterator(); 956 while (iter.hasNext()) { 957 Long time = iter.next(); 958 if (time != null) { 959 counter++; 960 result = result * ((counter - 1) / (double) counter) + 961 time.longValue()/(double) counter; 962 } 963 } 964 return (long) result; 965 } 966 967 /** 968 * Initializes pool statistics. 969 */ 970 private void initStats() { 971 for (int i = 0; i < MEAN_TIMING_STATS_CACHE_SIZE; i++) { 972 activeTimes.add(null); 973 idleTimes.add(null); 974 waitTimes.add(null); 975 } 976 } 977 978 979 // Inner classes 980 981 /** 982 * The idle object evictor {@link TimerTask}. 983 * 984 * @see GenericKeyedObjectPool#setTimeBetweenEvictionRunsMillis 985 */ 986 class Evictor extends TimerTask { 987 /** 988 * Run pool maintenance. Evict objects qualifying for eviction and then 989 * ensure that the minimum number of idle instances are available. 990 * Since the Timer that invokes Evictors is shared for all Pools but 991 * pools may exist in different class loaders, the Evictor ensures that 992 * any actions taken are under the class loader of the factory 993 * associated with the pool. 994 */ 995 @Override 996 public void run() { 997 ClassLoader savedClassLoader = 998 Thread.currentThread().getContextClassLoader(); 999 try { 1000 // Set the class loader for the factory 1001 Thread.currentThread().setContextClassLoader( 1002 factoryClassLoader); 1003 1004 // Evict from the pool 1005 try { 1006 evict(); 1007 } catch(Exception e) { 1008 swallowException(e); 1009 } catch(OutOfMemoryError oome) { 1010 // Log problem but give evictor thread a chance to continue 1011 // in case error is recoverable 1012 oome.printStackTrace(System.err); 1013 } 1014 // Re-create idle instances. 1015 try { 1016 ensureMinIdle(); 1017 } catch (Exception e) { 1018 swallowException(e); 1019 } 1020 } finally { 1021 // Restore the previous CCL 1022 Thread.currentThread().setContextClassLoader(savedClassLoader); 1023 } 1024 } 1025 } 1026}