堆满了com.mysql.jdbc.JDBC4Connection

时间:2018-07-18 20:40:43

标签: java mysql spring hibernate c3p0

我正在分析堆转储,其中我在堆中设置了50%的活动空间。这是由于为保留所有JDBC4Connection而保留的大量堆及其内部属性哈希表引起的。这是运行了几天的应用程序的堆转储。

enter image description here

看起来它正在容纳数千个JDBC连接对象及其配置。

enter image description here

我发现了一个提出类似问题的问题,但被驳回并提示用户未关闭连接:Too many instances of "com.mysql.jdbc.JDBC4Connection"

但是,我使用的是org.springframework.data.jpa.repository.JpaSpecificationExecutor.findAll,而没有直接查询数据库。代码:

Specification<AccountProfile> spec = getUserInfoListSurfacing(userInfo);
JPAImpl.findAll(spec, new PageRequest(0, 1, Sort.Direction.DESC, "reportedDate")).getContent()

这是此连接池的bean定义

<bean id="db" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="dataSourceName" value="users"/>
        <property name="driverClass" value="${userdb.driver}"/>
        <property name="forceUseNamedDriverClass" value="true"/>
        <property name="jdbcUrl" value="${userdb.url}"/>
        <property name="user" value="${userdb.username}"/>
        <property name="password" value="${userdb.password}"/>
        <property name="initialPoolSize" value="${userdb.hibernate.c3p0.initialPoolSize}"/>
        <property name="maxPoolSize" value="${userdb.hibernate.c3p0.max_size}"/>
        <property name="minPoolSize" value="${userdb.hibernate.c3p0.min_size}"/>
        <property name="idleConnectionTestPeriod" value="${userdb.hibernate.c3p0.idle_test_period}"/>
        <property name="maxStatements" value="${userdb.hibernate.c3p0.max_statements}"/>
        <property name="maxIdleTime" value="${userdb.hibernate.c3p0.idle_test_period}"/>
        <property name="preferredTestQuery" value="${userdb.hibernate.c3p0.validationQuery}"/>
        <property name="testConnectionOnCheckout" value="${userdb.hibernate.c3p0.testOnBorrow}"/>
        <property name="acquireIncrement" value="${userdb.hibernate.c3p0.acquireincrement}"/>
        <property name="unreturnedConnectionTimeout"
                  value="${userdb.hibernate.c3p0.unreturnedConnectionTimeout}"/>
        <property name="debugUnreturnedConnectionStackTraces" value="${userdb.hibernate.c3p0.debugUnreturnedConnectionStackTraces}"/>
        <property name="maxConnectionAge" value="${userdb.hibernate.c3p0.maxconnectionage}"/>
        <property name="numHelperThreads" value="${userdb.hibernate.c3p0.numHelperThreads}"/>
        <property name="connectionCustomizerClassName" value="${userdb.hibernate.c3p0.connectionCustomizerClassName}"/>
    </bean>

我在所使用的Hibernate版本中找不到已确认的内存泄漏报告。

我正在使用spring-data-jpa 2.0.6版。最终 hibernate-core版本4.3.5.Final hibernate-jpa-2.1-api版本1.0.2。最终版本

1 个答案:

答案 0 :(得分:1)

您显示对象“托管”的224个实例。每个连接池都有一个“托管”实例,因此您有224个连接池,它们保存对连接的引用,而不仅仅是一个。您必须了解为什么当典型的应用程序只想要一个池时,为什么要实例化如此多的池。

可能导致此错误的常见错误是每次您要建立新的连接时都要创建一个新的连接池。不太常见的原因是使用相同的DataSource在使用dataSource.getConnection(user,password)的多个身份验证下建立连接。每个不同的身份验证都会建立一个新的连接池。

由于您不是直接实例化Connection池,而是使用Spring来实例化它,因此调试任何实例化实例的原因并不是那么容易。您绝对应该添加的一件事是destroy-method XML标签的bean属性。那是...

<bean id="db" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
   ...
</bean>

您可能只是通过大量重新部署应用程序而生成所有这些池,并且由于Spring不知道必须清理您的bean而无法清理旧池。参见Spring的Destruction Callbacks