radioAe6rt

HsqlDb memory leak?

with 2 comments

I got on a Spring+Hibernate bender recently, determined to learn a few new things about declarative transaction management and annotating entity classes using Hibernate Annotations. In the course of this work, one needs a database, and the one I’m using is embedded HSQL and happens to contain about 1M records. To populate it I elected to use Spring’s JdbcTemplate helper class.

A few minutes into the population of the database, the JVM would issue an OutofMemoryError. Hours of debugging ensued, as I made certain that my code was not holding onto references that should have been garbage-collected.

I finally accepted the fact that a heap profile was in order, so I set -XX:+HeapDumpOnOutOfMemoryError on the JVM command line. The app harness is a Jetty webapp, so the application invocation goes like this:

$ java -XX:+HeapDumpOnOutOfMemoryError -jar start.jar

When the app died for lack of memory, it wrote java_pidXXX.hprof to the current working directory. JDK6 now bundles jhat, a heap analysis tool for just this sort of occasion:

$ jdk/jdk1.6.0/bin/jhat -port 1960 -J-mx512m tmp/java_pid13056.hprof

which after considerable crunching, starts a web server on port 1960 with the results of the analysis. Toward the bottom of the output, one finds “Show instance counts for all classes (excluding platform)”, whereupon I was presented with something like 500,000 held-references to org.hsqldb.MemoryNode and org.hsqldb.Row. This was for HsqlDb v1.8.0.7, using cached tables. I’m not an expert at reading this hprof output, but from the looks of it, those two classes hold references to each other that neither releases.

So I swapped HsqlDb out and the latest Apache Derby in, and the database loads fine. I can even see in the JVM profiler output (http://www.yourkit.com) how allocated heap memory now stays within safe boundaries.

It was a good exercise tracking down this memory issue, and good that another tool could be added to the set: jhat.

Update: A user in the know on the HsqlDb forum indicated that for cached tables, this OOM error should not obtain. By using jdbc:hsqldb:data/qsodb;hsqldb.default_table_type=cached for the JDBC connection URL, I was able to confirm his assertion. Setting what I thought was the equivalent property in the Hibernate sessionFactory properties hibernate.connection.hsqldb.default_table_type=cached did not have the same effect, at least not at the time the app needed it. All these tests can be verified by examining the HsqlDb properties file theDb.properties after the app starts up.

[tags]hsqldb,derby,spring,hibernate,jhat[/tags]

Written by radioae6rt

September 1, 2007 at 9:59 am

Posted in Internet

2 Responses

Subscribe to comments with RSS.

  1. Please read the HSQLDB Guide. This is not a memory leak. By default, HSQLDB creates memory tables, which store all the data in memory. You need to use CACHED tables when you don’t want to use a lot of memory.

    Fred Toussi

    September 2, 2007 at 12:58 am

  2. Say what?
    :)

    Fran Padow

    September 2, 2007 at 6:24 am


Leave a Reply