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