Druid-代码段-4-3
本代码段对应流程4.2,防止内存泄漏的连接关闭检测:
//回收长期未归还的连接(再次说明:该方法仅在removeAbandoned设置为true的情况下触发)
public int removeAbandoned() {
int removeCount = 0;
long currrentNanos = System.nanoTime();
//这个列表用于存放满足条件的真正需要强制回收的连接
List abandonedList = new ArrayList();
activeConnectionLock.lock();
try {
//在removeAbandoned设置为true的情况下,所有被借出去的连接,都会被保存进activeConnections(参考主流程1),所以要进行“长期未归还”的检查,就是从activeConnections开始的
Iterator iter = activeConnections.keySet().iterator();
for (; iter.hasNext();) {
DruidPooledConnection pooledConnection = iter.next();
if (pooledConnection.isRunning()) {
continue; //如果当前连接正在使用中(指的是正在execute),则不处理
}
//利用当前时间和连接被借出去时的时间,计算出连接被借出去的时间有多久
long timeMillis = (currrentNanos - pooledConnection.getConnectedTimeNano()) / (1000 * 1000);
if (timeMillis >= removeAbandonedTimeoutMillis) { //如果连接被借出去的时间超过removeAbandonedTimeoutMillis这个阈值,将会命中“主动归还”的逻辑检查
iter.remove(); //先从activeConnections移除
pooledConnection.setTraceEnable(false); //标记为false,防止回收时重复removeactiveConnections,可以参考主流程5
abandonedList.add(pooledConnection); //放入“强制回收”队列
}
}
} finally {
activeConnectionLock.unlock();
}
if (abandonedList.size() > 0) { //如果“强制回收”队列大于0,说明有需要回收的连接
for (DruidPooledConnection pooledConnection : abandonedList) { //循环这些连接
final ReentrantLock lock = pooledConnection.lock;
lock.lock(); //拿到连接的锁
try {
if (pooledConnection.isDisable()) {
continue; //已经被回收的,则不管
}
} finally {
lock.unlock();
}
//触发回收连接对象(pooledConnection)里的holcder(注意这里其实是把pooledConnection对象里的holder给回收至连接池了,pooledConnection对象本身会被销毁)
JdbcUtils.close(pooledConnection); //这里触发的close,是DruidPooledConnection的close,也就是会触发recycle方法的close
pooledConnection.abandond(); //标记为
removeAbandonedCount++;
removeCount++;
if (isLogAbandoned()) { //日志打印,忽略
StringBuilder buf = new StringBuilder();
buf.append("abandon connection, owner thread: ");
buf.append(pooledConnection.getOwnerThread().getName());
buf.append(", connected at : ");
buf.append(pooledConnection.getConnectedTimeMillis());
buf.append(", open stackTrace\n");
StackTraceElement[] trace = pooledConnection.getConnectStackTrace();
for (int i = 0; i < trace.length; i++) {
buf.append("\tat ");
buf.append(trace[i].toString());
buf.append("\n");
}
buf.append("ownerThread current state is " + pooledConnection.getOwnerThread().getState()
+ ", current stackTrace\n");
trace = pooledConnection.getOwnerThread().getStackTrace();
for (int i = 0; i < trace.length; i++) {
buf.append("\tat ");
buf.append(trace[i].toString());
buf.append("\n");
}
LOG.error(buf.toString());
}
}
}
return removeCount; //返回本次被强制回收的连接个数
}