Hibernate version:
3.1.3
Full stack trace of any exception that occurs:
2006-05-12 01:14:15,387 ERROR SocketListener0-1 proxy.BasicLazyInitializer CGLIB Enhancement failed: com.test.MyBean
2006-05-12 01:14:15,479 ERROR SocketListener0-1 proxy.BasicLazyInitializer net.sf.cglib.core.CodeGenerationException: java.lang.reflect.InvocationTargetException-->null
2006-05-12 01:14:24,121 ERROR SocketListener0-1 tasks.BaseTask -run() Throwable: PermGen space
2006-05-12 01:14:24,121 ERROR SocketListener0-1 tasks.BaseTask java.lang.OutOfMemoryError: PermGen space.
Name and version of the database you are using:
DB2 8.2.2
DB2 8.1.6
DB2 8.1.3
HSQLDB 1.8.0.4
Description
The memory leak has been reproduced both on Win and Linux, with jdk1.5.0_06.
I have an application/service that use a large number of different db users against one database. The service is called to perform predefined, similar, tasks against different schemas with separate users. For each task only one or a few connection setups are needed.
Since tasks are not performed concurrently, connection pools may remain unused for ~5-60mins. Keeping lots of of resources and unused connections per instance of this service seemed unnecessary, especially since there are several other applications and servers that use the same database. (Even though the connection pool could be configured to use a small min-size...)
So, each task created the required SessionFactories and when done they would call close() on the SessionFactory and discard it.
When debugging the application with jconsole it was very obvious that it leaked memory in the PermGen space and in the test environment it crashed after some time. But if we kept the SessionFactories open and reused them, the server remained stable.
To isolate the problem I created a simple loop that just creates and closes SessionFactory instances and the problem remained:
Code:
SessionFactory sf;
Configuration cfg = new AnnotationConfiguration()
.addAnnotatedClass(Service.class);
while (true)
{
sf = cfg.buildSessionFactory();
Session s = sf.openSession();
Query q = s.createQuery("from Service");
for (Service row : (List<Service>) q.list()) {
System.out.println(row.getSName() + " " + row.getSDescription());
}
s.close();
sf.close();
}
I have tried this with and without hibernate-annotations (not that it should matter?), with c3p0 and with a simpler home-made ConnectionProvider, with different mappings, and with different JDBC-drivers (DB2 and HSQLDB). But the result is always the same; the test grows in PermGen memory and finally it just stops executing.
So, before I start digging deeper into this; does anyone know why this happens? Perhaps SessionFactories are not supposed to be used in this way (created and destroyed often during runtime)? Could it be ehcache or cglib that are not pleased with this approach? I could not find any posts that was clearly related to this issue and I'm quite new to hibernate.
Even if I decide to keep all SessionFactory instances between tasks it would be interesting to know why this error occurs...