问题描述
现在有一个长时间的增删改查操作,操作量很大,项目试用Druid作为连接池,启用StatFilter,过了一段时间,内存泄露,通过dump jvm的内存快照分析得知,是DruidDataSource.JdbcDataSourceStat.ConcurrentMap<Long, JdbcConnectionStat.Entry>占用了近一半的内存导致的。
Debug分析
- 首先找到是StatFilter里面connection_connect方法对map进行put值
- 在DruidDataSource中的getConnection()方法唤醒了创建物理连接的线程CreateConnectionThread
- 为什么会每次get连接都是创建物理连接呢?是因为每次获取连接,执行pollLast(),在判断poolingCount==0命中后执行方法emptySignal()唤醒了生产线程
- 为什么poolingCount会等于0呢?我的初始连接数是3个,前三次获取都不会唤醒生产线程,从第四次开始就开始创建物理连接了。
- 为什么poolingCount只会一直减少呢?发现在DruidDataSource执行方法recycle()时并没有执行到
putLast(holder, currentTimeMillis)
就returne了,而方法putLast(holder, currentTimeMillis)
正是执行poolingCount++
的地方。 - 然后继续debug,在recycle()方法里的以下代码出进入if最终导致return的
if (physicalConnection.isClosed()) {
lock.lock();
try {
activeCount--;
closeCount++;
} finally {
lock.unlock();
}
return;
}
physicalConnection.isClosed()
方法存在两个具体实现类,DruidPooledConnection
和ConnectionProxyImpl
,就是在执行一套FilterChain后判断结果为true导致的返回。
@wenshao
比较郁闷,为什么在判断是否关闭时 是真呢?
1条答案
按热度按时间41zrol4v1#
贴出我的druid配置