Hibernate version:
3.0
Name and version of the database you are using:
MySQL 4.1
Hi,
I need help to save my project :-S
I am using Tomcat 5.5.4 for a project with a little amount of data and I often have OutOfMemoryErrors.
I noticed the following (Win2000 tasks manager) :
- tomcat uses about 30MB for his basic work
- tomcat uses 3 or 5 MB he never relases for restarting a context
- 10 or 12MB are needed for the reading of the configuration files (never released).
- when I am using the application, everything works fine and the memory usage seems to be constant.
I dont know if the problem will also occurs in production, but it occurs about 10 times a day in developpement (Tomcat crashes with OOME after 120MB).
Please give me some ideas to solve that...
Below, my hibernate.cfg.xml, one typical mapping file, my HibernateUtil (from CaveatEmptor), my HibernateFilter (from CaveatEmptor) and one typical DAO.
Best regards
Lilian
HibernateUtil (from CaveatEmptor) :
Code:
import org.apache.commons.logging.*;
import org.hibernate.*;
import org.hibernate.cfg.*;
import bab.admin.model.exceptions.*;
public class HibernateUtil
{
private static Log log = LogFactory.getLog( HibernateUtil.class );
private static int configurationReaded = 0;
private static Configuration configuration;
private static SessionFactory sessionFactory;
private static final ThreadLocal threadSession = new ThreadLocal();
private static final ThreadLocal threadTransaction = new ThreadLocal();
private static final ThreadLocal threadInterceptor = new ThreadLocal();
// Create the initial SessionFactory from the default configuration files
static
{
try
{
configuration = new Configuration();
sessionFactory = configuration.configure().buildSessionFactory();
System.out.println( "configuration lue : " +(++configurationReaded)+ "
fois." );
// We could also let Hibernate bind it to JNDI:
// configuration.configure().buildSessionFactory()
}
catch ( Throwable ex )
{
// We have to catch Throwable, otherwise we will miss
// NoClassDefFoundError and other subclasses of Error
log.error( "Building SessionFactory failed.", ex );
throw new ExceptionInInitializerError( ex );
}
}
/**
* Returns the SessionFactory used for this static class.
*
* @return SessionFactory
*/
public static SessionFactory getSessionFactory()
{
/* Instead of a static variable, use JNDI:
SessionFactory sessions = null;
try {
Context ctx = new InitialContext();
String jndiName = "java:hibernate/HibernateFactory";
sessions = (SessionFactory)ctx.lookup(jndiName);
} catch (NamingException ex) {
throw new InfrastructureException(ex);
}
return sessions;
*/
return sessionFactory;
}
/**
* Returns the original Hibernate configuration.
*
* @return Configuration
*/
public static Configuration getConfiguration()
{
return configuration;
}
/**
* Rebuild the SessionFactory with the static Configuration.
*
*/
public static void rebuildSessionFactory() throws InfrastructureException
{
synchronized ( sessionFactory )
{
try
{
sessionFactory = getConfiguration().buildSessionFactory();
}
catch ( Exception ex )
{
throw new InfrastructureException( ex );
}
}
}
/**
* Rebuild the SessionFactory with the given Hibernate Configuration.
*
* @param cfg
*/
public static void rebuildSessionFactory( Configuration cfg ) throws
InfrastructureException
{
synchronized ( sessionFactory )
{
try
{
sessionFactory = cfg.buildSessionFactory();
configuration = cfg;
}
catch ( Exception ex )
{
throw new InfrastructureException( ex );
}
}
}
/**
* Retrieves the current Session local to the thread.
* <p/>
* If no Session is open, opens a new Session for the running thread.
*
* @return Session
*/
public static Session getSession() throws InfrastructureException
{
Session s = (Session)threadSession.get();
try
{
if ( s == null )
{
System.out.println( "Ouverture d'une nouvelle session pour ce Thread" );
//log.debug( "Opening new Session for this thread." );
log.info( "Opening new Session for this thread." );
if ( getInterceptor() != null )
{
//log.debug( "Using interceptor: " + getInterceptor().getClass() );
log.info( "Using interceptor: " + getInterceptor().getClass() );
s = getSessionFactory().openSession( getInterceptor() );
}
else
{
s = getSessionFactory().openSession();
}
threadSession.set( s );
}
}
catch ( HibernateException ex )
{
throw new InfrastructureException( ex );
}
return s;
}
/**
* Closes the Session local to the thread.
*/
public static void closeSession() throws InfrastructureException
{
try
{
Session s = (Session)threadSession.get();
threadSession.set( null );
if ( s != null && s.isOpen() )
{
System.out.println( "Fermeture de la session pour ce thread + vidage du
cache + garbage collect");
//log.debug( "Closing Session of this thread." );
log.info( "Closing Session of this thread." );
s.clear();
s.close();
System.gc();
}
}
catch ( HibernateException ex )
{
throw new InfrastructureException( ex );
}
}
/**
* Start a new database transaction.
*/
public static void beginTransaction() throws InfrastructureException
{
Transaction tx = (Transaction)threadTransaction.get();
try
{
if ( tx == null )
{
System.out.println( "Début d'une nouvelle transaction pour ce Thread" );
log.debug( "Starting new database transaction in this thread." );
tx = getSession().beginTransaction();
threadTransaction.set( tx );
}
}
catch ( HibernateException ex )
{
throw new InfrastructureException( ex );
}
}
/**
* Commit the database transaction.
*/
public static void commitTransaction() throws InfrastructureException
{
Transaction tx = (Transaction)threadTransaction.get();
try
{
if ( tx != null && !tx.wasCommitted() && !tx.wasRolledBack() )
{
System.out.println( "Commit de la transaction pour ce thread" );
log.debug( "Committing database transaction of this thread." );
tx.commit();
}
threadTransaction.set( null );
}
catch ( HibernateException ex )
{
rollbackTransaction();
throw new InfrastructureException( ex );
}
}
/**
* Commit the database transaction.
*/
public static void rollbackTransaction() throws InfrastructureException
{
Transaction tx = (Transaction)threadTransaction.get();
try
{
threadTransaction.set( null );
if ( tx != null && !tx.wasCommitted() && !tx.wasRolledBack() )
{
System.out.println( "Rollback de la transaction pour ce thread ");
log.debug( "Tyring to rollback database transaction of this thread." );
tx.rollback();
}
}
catch ( HibernateException ex )
{
throw new InfrastructureException( ex );
}
finally
{
closeSession();
}
}
/**
* Reconnects a Hibernate Session to the current Thread.
*
* @param session The Hibernate Session to be reconnected.
*/
public static void reconnect( Session session ) throws
InfrastructureException
{
try
{
System.out.println( "reconnect session");
session.reconnect();
threadSession.set( session );
}
catch ( HibernateException ex )
{
throw new InfrastructureException( ex );
}
}
/**
* Disconnect and return Session from current Thread.
*
* @return Session the disconnected Session
*/
public static Session disconnectSession() throws InfrastructureException
{
Session session = getSession();
try
{
System.out.println( "disconnect session ");
threadSession.set( null );
if ( session.isConnected() && session.isOpen() ) session.disconnect();
}
catch ( HibernateException ex )
{
throw new InfrastructureException( ex );
}
return session;
}
/**
* Register a Hibernate interceptor with the current thread.
* <p>
* Every Session opened is opened with this interceptor after
* registration. Has no effect if the current Session of the
* thread is already open, effective on next close()/getSession().
*/
public static void registerInterceptor( Interceptor interceptor )
{
threadInterceptor.set( interceptor );
}
private static Interceptor getInterceptor()
{
Interceptor interceptor = (Interceptor)threadInterceptor.get();
return interceptor;
}
}
HibernateFilter (from CaveatEmptor) :Code:
package bab.admin.web.filter;
import org.apache.commons.logging.*;
import bab.admin.model.*;
import java.io.IOException;
import javax.servlet.*;
/**
* A servlet filter that opens and closes a Hibernate Session for each
request.
* <p>
* This filter guarantees a sane state, committing any pending database
* transaction once all other filters (and servlets) have executed. It also
* guarantees that the Hibernate <tt>Session</tt> of the current thread will
* be closed before the response is send to the client.
* <p>
* Use this filter for the <b>session-per-request</b> pattern and if you are
* using <i>Detached Objects</i>.
*
* @see HibernateUtil
* @author Christian Bauer <christian@hibernate.org>
*
* @web.filter
* name="HibernateFilter"
* @web.filter-mapping url-pattern="/*"
*/
public class HibernateFilter implements Filter
{
private static Log log = LogFactory.getLog( HibernateFilter.class );
public void init( FilterConfig filterConfig ) throws ServletException
{
log.info( "Servlet filter init, now opening/closing a Session for each
request." );
}
public void doFilter( ServletRequest request, ServletResponse response,
FilterChain chain ) throws IOException, ServletException
{
// There is actually no explicit "opening" of a Session, the
// first call to HibernateUtil.beginTransaction() in control
// logic (e.g. use case controller/event handler) will get
// a fresh Session.
try
{
chain.doFilter( request, response );
// Commit any pending database transaction.
HibernateUtil.commitTransaction();
}
finally
{
// No matter what happens, close the Session.
HibernateUtil.closeSession();
}
}
public void destroy()
{
}
}
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>
<property name="hibernate.connection.username">root</property>
<property
name="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>
<property
name="hibernate.connection.url">jdbc:mysql://localhost/babadmin</property>
<property
name="hibernate.connection.driver_class">org.gjt.mm.mysql.Driver</property>
<property name="show_sql">true</property>
<property name="hibernate.generate_statistics">true</property>
<mapping resource="bab/admin/model/persistent/Worker.hbm.xml" />
<mapping resource="bab/admin/model/persistent/Activity.hbm.xml" />
<mapping resource="bab/admin/model/persistent/City.hbm.xml" />
<mapping resource="bab/admin/model/persistent/Quartier.hbm.xml" />
<mapping resource="bab/admin/model/persistent/ContactPoint.hbm.xml"
/>
<mapping
resource="bab/admin/model/persistent/MailContactPoint.hbm.xml" />
<mapping
resource="bab/admin/model/persistent/PhoneContactPoint.hbm.xml" />
<mapping
resource="bab/admin/model/persistent/EmailContactPoint.hbm.xml" />
<mapping
resource="bab/admin/model/persistent/FaxContactPoint.hbm.xml" />
<mapping
resource="bab/admin/model/persistent/MobileContactPoint.hbm.xml" />
<mapping resource="bab/admin/model/persistent/Employee.hbm.xml" />
<mapping resource="bab/admin/model/persistent/IParty.hbm.xml" />
<mapping resource="bab/admin/model/persistent/Speciality.hbm.xml" />
<mapping resource="bab/admin/model/persistent/Client.hbm.xml" />
<mapping resource="bab/admin/model/persistent/ClientPerson.hbm.xml"
/>
<mapping
resource="bab/admin/model/persistent/ClientOrganization.hbm.xml" />
<mapping resource="bab/admin/model/persistent/Contact.hbm.xml" />
<mapping resource="bab/admin/model/persistent/Evaluation.hbm.xml" />
<mapping
resource="bab/admin/model/persistent/ClientEvaluation.hbm.xml" />
<mapping
resource="bab/admin/model/persistent/WorkerEvaluation.hbm.xml" />
<mapping
resource="bab/admin/model/persistent/OrganizationType.hbm.xml" />
<mapping resource="bab/admin/model/persistent/Job.hbm.xml" />
<mapping resource="bab/admin/model/persistent/JobPeriod.hbm.xml" />
<mapping resource="bab/admin/model/persistent/JobWorker.hbm.xml" />
<mapping resource="bab/admin/model/persistent/PeriodWorker.hbm.xml"
/>
<mapping resource="bab/admin/model/persistent/Tarif.hbm.xml" />
<mapping resource="bab/admin/model/persistent/SalaryRule.hbm.xml" />
<mapping resource="bab/admin/model/persistent/Misc.hbm.xml" />
<mapping resource="bab/admin/model/persistent/PersonData.hbm.xml" />
</session-factory>
</hibernate-configuration>
One typical mapping document :<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
<hibernate-mapping>
<class name="bab.admin.model.persistent.Job" table="t_service"
dynamic-update="false" dynamic-insert="false"
select-before-update="false" optimistic-lock="version">
<id name="id" column="serviceId" type="java.lang.Integer">
<generator class="native">
</generator>
</id>
<many-to-one
name="client"
column="clientPartyId"
lazy="true" />
<many-to-one
name="contactForBAB"
column="employeePartyId"
lazy="true" />
<set
name="contactsForClient"
table="t_clientcontact"
inverse="true"
cascade="all">
<key column="serviceId" />
<many-to-many
class="bab.admin.model.persistent.Contact"
column="partyId" />
</set>
<set
name="periods"
inverse="true"
cascade="all"
order-by="startDate">
<key column="serviceId" />
<one-to-many
class="bab.admin.model.persistent.JobPeriod" />
</set>
<set
name="jobWorkers"
inverse="true"
cascade="all" >
<key column="serviceId" />
<one-to-many
class="bab.admin.model.persistent.JobWorker" />
</set>
<many-to-one
name="tarif"
column="tarifId"
cascade="all"
lazy="true" />
<one-to-one name="evaluation" />
<many-to-one
name="address"
cascade="all"
column="contactPointId" />
<property name="fileId" />
<property
name="title"
column="jobTitle" />
<property
name="description"
column="jobDescription" />
<property
name="begin"
column="contactDate" />
<property
name="close"
column="closeDate" />
<property
name="contract"
column="contractDate" />
<property
name="feedback"
column="babFeedback" />
<property
name="comment" />
<component name="invoice">
<property
name="sent"
column="invoiceDate" />
<property
name="number"
column="invoiceNumber" />
<property name="comment"
column="invoiceComment" />
<property name="otherCharges" />
<property name="otherChargesDescription" />
</component>
</class>
</hibernate-mapping>
One typical DAO :Code:
package bab.admin.model.dao;
import java.util.*;
import org.apache.commons.logging.*;
import org.hibernate.*;
import bab.admin.model.*;
import bab.admin.model.exceptions.*;
/**
* Fonctions de bases d'accès aux données de la base par Hibernate
* @author lilian
* TODO ajouter le logging des erreurs et autres
*/
public class DefaultDAO
{
private static DefaultDAO dao = new DefaultDAO();
private static Log log = LogFactory.getLog(HibernateUtil.class);
public static DefaultDAO instance()
{
return dao;
}
protected void log( String message, Throwable ex )
{
log.error( message, ex );
}
public Object getById( Integer id, Class clazz ) throws
InfrastructureException
{
Session session = HibernateUtil.getSession();
Object object = null;
try
{
object = session.get( clazz, id );
}
catch ( HibernateException ex )
{
throw new InfrastructureException( ex );
}
return object;
}
// ********************************************************** //
public Collection select( String hql ) throws InfrastructureException
{
Session session = HibernateUtil.getSession();
try
{
Query q = session.createQuery( hql );
return q.list();
}
catch ( InfrastructureException e )
{
throw new InfrastructureException( e );
}
}
public Collection findAll( Class clazz ) throws InfrastructureException
{
try
{
Session session = HibernateUtil.getSession();
Criteria crit = session.createCriteria( clazz );
return crit.list();
}
catch ( HibernateException ex )
{
throw new InfrastructureException( ex );
}
}
// ********************************************************** //
/**
* @return en général, l'id généré
*/
public Object save( Object object ) throws InfrastructureException
{
try
{
Session session = HibernateUtil.getSession();
Transaction tx = session.beginTransaction();
Object o = session.save( object );
tx.commit();
HibernateUtil.closeSession();
return o;
}
catch ( HibernateException ex )
{
throw new InfrastructureException( ex );
}
}
public void save( Collection objects ) throws InfrastructureException
{
try
{
Session session = HibernateUtil.getSession();
Transaction tx = session.beginTransaction();
//TODO flusher régulièrement les données dans le cas où la
collection serait très grande
for ( Iterator iter = objects.iterator(); iter.hasNext(); )
{
Object object = iter.next();
session.save( object );
}
HibernateUtil.closeSession();
}
catch ( HibernateException ex )
{
throw new InfrastructureException( ex );
}
}
// ********************************************************** //
public void update( Object object ) throws InfrastructureException
{
try
{
Session session = HibernateUtil.getSession();
Transaction tx = session.beginTransaction();
session.saveOrUpdate( object );
tx.commit();
HibernateUtil.closeSession();
}
catch ( HibernateException ex )
{
throw new InfrastructureException( ex );
}
}
// ********************************************************** //
public void delete( Object object ) throws InfrastructureException
{
try
{
Session session = HibernateUtil.getSession();
Transaction tx = session.beginTransaction();
session.delete( object );
tx.commit();
}
catch ( HibernateException ex )
{
throw new InfrastructureException( ex );
}
}
}
Full stack trace of any exception that occurs:
OutOfMemoryError : PermGen space