My Java program which uses Hibernate is falling over on me with an OutOfMemoryError exception. I'd appreciate any advice on how to reduce the memory usage. Do I need to disable some caching that Hibernate does by default? Do I need to reduce some cache size?
Some BackgroundI have a problem with a Java program that I have written and I was hoping to use Hibernate to help me solve it. My Java program generates loads of objects and consumes large amounts of memory. So I was hoping to use Hibernate to store the objects in a database and then just retrieve them when I need them.
Test ProgramSo to test this, I decided to create a large number of objects and store them to the database using Hibernate to ensure that the memory usage did not rise. Each time I would create an object I would save it to the database and then dereference the object straight away. Below is my little bit of code. When I run this code it falls over with an java.lang.OutOfMemoryError exception.
I decided then to profile the code and it seems the large amounts of memory are being used up in instances of these two classes
org.hibernate.engine.EntityEntry
org.hibernate.engine.EntityKey
So, pretty much a 1-to-1 mapping for each object I save to the database. I presume that Hiberate is holding on to the reference in some cache? But how do I clear this so that my memory usage stays constant regardless of how many objects I create (i.e. stays constant after a certain startup period)?
My CodeCode:
---------------------------------------------------------
Main Java Class
---------------------------------------------------------
SessionFactory sessions = new Configuration().configure().buildSessionFactory();
Session session = sessions.openSession();
try {
for (int i = 1; i <= 500000; i++){
Person p1 = new Person();
p1.setName("Person" + i);
session.save(p1);
p1 = null;
if (i % 1000 == 0){
System.out.println(i + " objects");
session.flush();
}
}
} catch ( HibernateException e ) {
e.printStackTrace();
} finally {
session.close();
}
----------------------------------------------------------------
My Entity Java Class
---------------------------------------------------------
import java.io.Serializable;
public class Person implements Serializable {
private int id;
private String name;
protected Person() {
}
public Person(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
---------------------------------------------------------
hibernate.cfg.xml
---------------------------------------------------------
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- Database connection settings -->
<property name="connection.driver_class">org.apache.derby.jdbc.ClientDriver</property>
<property name="connection.url">jdbc:derby://localhost:1527/myDB</property>
<property name="connection.username">me</property>
<property name="connection.password">mine</property>
<property name="connection.autocommit">true</property>
<!-- JDBC connection pool (use the built-in) -->
<property name="connection.pool_size">1</property>
<!-- SQL dialect -->
<property name="dialect">org.hibernate.dialect.DerbyDialect</property>
<!-- Echo all executed SQL to stdout -->
<property name="show_sql">false</property>
<!-- Mapping files -->
<mapping resource="Person.hbm.xml"/>
</session-factory>
</hibernate-configuration>