Search code examples
javamysqlhibernatememory-leaksc3p0

Possible memory leak in c3p0 in Hibernate?


We use c3p0 as the pooling library in Hibernate with the configuration below. We suspect that there might be a memory leak in this library. We dump the memory heap of the application and it shows one object of type "com.mchange.v2.c3p0.stmt.GlobalMaxOnlyStatementCache" uses 2.2GB memory (61.6% of all) and it continues to grow until it runs out of memory. This class is used to cache PreparedStatements as far as I understand it. Our configuration uses 100 for this value, which means at most 100 statements should be cached.

configuration
    .setProperty("hibernate.c3p0.max_size", "25")
    .setProperty("hibernate.c3p0.min_size", "2")
    .setProperty("hibernate.c3p0.initial_pool_size", "2")
    .setProperty("hibernate.c3p0.timeout", "3600")
    .setProperty("hibernate.c3p0.max_statements", "100")
    .setProperty("hibernate.c3p0.idle_test_period", "300")
    .setProperty("hibernate.c3p0.acquire_increment", "2")
    .setProperty("hibernate.c3p0.maxConnectionAge", "3600")
    .setProperty("hibernate.c3p0.numHelperThreads", "6")

Thanks in advance for your help!


Solution

  • Yes, it can really be a bug. I suggest to report your issue here.

    Three hints:

    1. Statement caching is by default disabled in c3p0. I think you can guess why.
    2. c3p0 is too easy to misconfigure.
    3. c3p0 is a (quite) mature library but unfortunately is also far from being optimal choice for JDBC connection pooling nowadays. I really recommend you trying out faster and more reliable HikariCP.

    In my opinion, HikariCP is also far more predictable and simpler to use than c3p0. Of course, you also have other connection-pooling libraries: DBCP, Tomcat pooling, BoneCP, Proxool etc. You may try some of them and pick the one that suits your app.

    So basically you have two options, turn-off JDBC statement caching in c3p0 and wait for a fix (or fix it independently and create Pull Request) or try some alternative.