Hi people,
I get memory leaks from the built-in TomEE JDBC connection pool,
using the default container-managed persistence and transactions.
I have some code in a Singleton EJB that does, essentially, this:
@PersistenceUnit(unitName = "MyApp")
EntityManagerFactory emf;
@Schedule(second="*/10", minute="*", hour="*")
public void tickTock() {
EntityManager em = emf.createEntityManager();
em.find(MyTrivialEntity.class, 1);
}
Every time tickTock() is invoked, jmap -histo:live reports objects
being added permanently to the heap:
num #instances #bytes class name
----------------------------------------------
[...]
270: 6 1584 com.mysql.jdbc.JDBC4PreparedStatement
322: 6 1056 com.mysql.jdbc.JDBC4ResultSet
These #instances and #bytes values increase at a steady pace,
and if I leave it running long enough this causes OutOfMemory.
The number of connections doesn't grow: both mysqladmin and jmap
consistently report 3 simultaneous connections all the time.
It doesn't matter if I use Eclipselink instead of OpenJPA.
But the memory leak goes away if I change the database from Mysql
to embedded Derby, so I assume there is some quirkiness in the
Mysql driver that is involved.
The memory leak also goes away if I revert to using commons-dbcp
for the pool.
MaxAge <N> is a workaround, but how do I choose <N> for any
specific load? This is not an attractive solution.
I searched a lot before I posted this, and I found recommendations
that you should always close SQL Statements and ResultSets before
returning connections to the pool. But I have to trust the container
to do this when I am using JPA, right? Or am I missing something?
Version info:
apache-tomee-1.5.1-plus (I also tried today's 1.5.2 snapshot)
mysql-connector-java-5.1.22
jdk-7u9
--
Bjorn Danielsson
Cuspy Code AB