GenericObjectPool 是 Apache Commons Pool 提供的对象池,使用的时候须要调用 borrowObject 获取一个对象,使用完之后须要调用 returnObject 归还对象,或者调用 invalidateObject 将这个对象标记为不可再用。html
实际应用中因为程序实现的问题,可能形成在一些极端的状况下出现 borrowObject/invalidateObject 没有被调用致使的泄漏问题。对象泄漏会致使对象池中的对象数量一直上升,达到设置的上限之后再调用 borrowObject 就会永远等待或者抛出 java.util.NoSuchElementException: Timeout waiting for idle object
异常。java
对于这种问题,一方面是从应用实现上进行排查,另外一方面能够经过 GenericObjectPool 自带的机制进行清理。apache
GenericObjectPool判断一个对象是否泄漏是根据对象最后一次使用或者最后一次borrow的时间进行判断的,若是超出了预设的值就会被认为是一个泄漏的对象被清理掉(PooledObjectFactory.destroyObject在这一过程当中会被调用)。抛弃时间能够经过 AbandonedConfig.setRemoveAbandonedTimeout 进行设置,时间单位是秒。code
设置了抛弃时间之后还须要打开泄漏清理才会生效。泄漏判断的开启能够经过两种方式:htm
从对象池中获取对象的时候进行清理 若是当前对象池中少于2个idle状态的对象或者 active数量>最大对象数-3 的时候,在borrow对象的时候启动泄漏清理。经过 AbandonedConfig.setRemoveAbandonedOnBorrow 为 true 进行开启。对象
启动定时任务进行清理 AbandonedConfig.setRemoveAbandonedOnMaintenance 设置为 true 之后,在维护任务运行的时候会进行泄漏对象的清理,能够经过 GenericObjectPool.setTimeBetweenEvictionRunsMillis 设置维护任务执行的时间间隔。get
GenericObjectPool<PoolObj> pool = new GenericObjectPool<PoolObj>(new MyPooledObjectFactory(),config); AbandonedConfig abandonedConfig = new AbandonedConfig(); abandonedConfig.setRemoveAbandonedOnMaintenance(true); //在Maintenance的时候检查是否有泄漏 abandonedConfig.setRemoveAbandonedOnBorrow(true); //borrow 的时候检查泄漏 abandonedConfig.setRemoveAbandonedTimeout(10); //若是一个对象borrow以后10秒尚未返还给pool,认为是泄漏的对象 pool.setAbandonedConfig(abandonedConfig); pool.setTimeBetweenEvictionRunsMillis(5000); //5秒运行一次维护任务