-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 posts ] 
Author Message
 Post subject: OutOfMemory even when using flush/clear
PostPosted: Tue May 12, 2009 7:31 am 
Newbie

Joined: Mon Oct 20, 2008 1:34 am
Posts: 6
Hi,

I have searched the forum before I decided to open this thread. There are already two threads that describe the same problem I am facing, but unfortunately there are no answers:

https://forum.hibernate.org/viewtopic.php?f=1&t=962074
https://forum.hibernate.org/viewtopic.php?f=1&t=987196

Let me describe what I am doing: I have a native sql query which I execute quite often (about 500 000 times). After 100 executions, i call flush() and clear() on the session to prevent an out of memory exception. The problem is that even with the flush() and clear() my app crashes after some time because there is no space any more on the heap.

I used a memory profiler to find out that there are a lot of BulkOperationCleanupAction objects hanging around on the heap. The number of those objects is approximately equal to the times I execute the native SQL query. After I saw that, I took a look at the source code of hibernate. What I found there was very interesting: A session has an ActionQueue which holds several lists for actions. One of this lists contains the BulkOperationCleanupAction objects.

Next i took a look at the clean() method of the session. In there the clean() method of the ActionQueue is called, which then calls clear on the internal lists, except for the one containing the BulkOperationCleanupActions:

Code:
updates.clear();
insertions.clear();
deletions.clear();
collectionCreations.clear();
collectionRemovals.clear();
collectionUpdates.clear();


Why is the BulkOperationCleanupAction list not cleared? What is the solution to the above problem? Is there any way to clear the executions too? Or should this be done in a completely different way?

I don't know if it is related to the above problem, but I am using statement caching. Furthermore I found out that the BulkOperationCleanupAction list is cleared when the transaction is commited.


Top
 Profile  
 
 Post subject: Re: OutOfMemory even when using flush/clear
PostPosted: Fri May 15, 2009 1:21 am 
Newbie

Joined: Mon Oct 20, 2008 1:34 am
Posts: 6
Here is a "short" example that shows that the ActionQueue.executions ArrayList is only cleared on transaction commits. A flush() / clear() call does not clear the executions list:

Code:
import java.lang.reflect.Field;
import java.util.Collection;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.engine.ActionQueue;
import org.hibernate.impl.SessionImpl;


public class TestMain {
   public static void main(String arg[]) throws Exception {
      
      // RequiredTable: create table test (col varchar(1));
      
      Configuration config = new Configuration();
      config.setProperty("hibernate.connection.driver_class", "com.mysql.jdbc.Driver");
      config.setProperty("hibernate.connection.url", "jdbc:mysql://localhost/TestDb");
      config.setProperty("hibernate.connection.username", "user");
      config.setProperty("hibernate.connection.password", "pass");
      
      SessionFactory sessionFactory = config.buildSessionFactory();
      Session session = sessionFactory.openSession();
      Query query = session.createSQLQuery("INSERT INTO test(col) VALUES (:value)");
      
      Field field = ActionQueue.class.getDeclaredField("executions");
      field.setAccessible(true);

      int curIteration = 0;
      query.setParameter("value", 'a');
      session.beginTransaction();
      
      while (true) {
         query.executeUpdate();
         
         Collection executions = (Collection) field.get(((SessionImpl)session).getActionQueue());
         System.out.println (executions.size());
         curIteration++;
         
         if ((curIteration % 100) == 0) {
            System.out.println ("flush() / clear() session");
            session.flush();
            session.clear();
         }
         
         if ((curIteration % 1000) == 0) {
            System.out.println ("commit transaction / begin transaction");
            session.getTransaction().commit();
            session.beginTransaction();
         }
      }
      
   }
}



Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.