druid StatFilter导致的内存泄漏

1l5u6lss  于 4个月前  发布在  Druid
关注(0)|答案(1)|浏览(71)

问题描述

现在有一个长时间的增删改查操作,操作量很大,项目试用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() 方法存在两个具体实现类, DruidPooledConnectionConnectionProxyImpl ,就是在执行一套FilterChain后判断结果为true导致的返回。

@wenshao
比较郁闷,为什么在判断是否关闭时 是真呢?

41zrol4v

41zrol4v1#

贴出我的druid配置

<bean  
  id="abstractDataSource"  
  abstract="true"  
  class="com.alibaba.druid.pool.DruidDataSource"  
  p:initialSize="3"  
  p:maxActive="5"  
  p:maxWait="5000"  
  p:proxyFilters-ref="druidFilters"  
  p:validationQuery="SELECT 1"  
  p:testOnBorrow="true"  
  p:testOnReturn="false"  
  p:testWhileIdle="true"  
  p:timeBetweenEvictionRunsMillis="7200000"  
  p:removeAbandoned="false"/>

相关问题