-->
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.  [ 24 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: Hiberante Memory Leak in dynamic ClassLoader
PostPosted: Wed Sep 06, 2006 2:45 pm 
Newbie

Joined: Wed Sep 06, 2006 2:33 pm
Posts: 13
I noticed the problem in this post
http://forum.hibernate.org/viewtopic.php?t=930270

But I found it is NOT a problem of Application Server. To prove this, I created two simple classes. "CallJunk" repeatedly creates a URLClassLoader , loads Junk and hibernate classes, and call Junk.main(). Junk.main() opens a session and closes it.

The CallJunk program grows 1-2 MB in each loop step and finally run out of memory.
I profiled with JProfiler, the URLClassLoader and hibernate classes are not GCed.

According to that post, I also tried upgrade CGLib to 2.2_beta1, no help; tried JDK1.5 and JDK1.4, no help; tried Introspector.flushCaches(), no help; tried hibernate.cglib.use_reflection_optimize=false, no help; my simple junk class does not use ThreadLocal.

Code:
package calljunk;

import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;

public class CallJunk {

   static String[] dum=new String[0];
   static Class[] parameterTypes = new Class[]{dum.getClass()};

   public static void main(String[] args)throws Exception {
      URL[] urls = new URL[]{
            new File("../junk/cglib-2.2_beta1.jar").toURL(),
            new File("../junk/commons-collections-2.1.1.jar").toURL(),
            new File("../junk/dom4j-1.6.1.jar").toURL(),
            new File("../junk/ehcache-1.2.jar").toURL(),
            new File("../junk/hibernate3.jar").toURL(),
            new File("../junk/jta.jar").toURL(),
            new File("../junk/postgresql-8.0-311.jdbc3.jar").toURL(),
            new File("../junk/commons-logging-1.0.4.jar").toURL(),
            new File("../junk/bin").toURL()
         };
      
      for (int i=0; i<1000; i++) {
         System.out.println("No "+i+": ");
         //System.in.read();
         Class cls = new URLClassLoader(urls).loadClass("junk.Junk");
         cls.getMethod("main", parameterTypes).invoke(null, new Object[]{dum});
      }
   }
}

package junk;
import java.beans.Introspector;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;

import javax.naming.InitialContext;

public class Junk {

    private static String CONFIG_FILE_LOCATION = "/hibernate.cfg.xml";

   public static void main(String[] args) throws Exception {
      Configuration cfg = new Configuration();
      SessionFactory sFactory = null;
      try {
         cfg.configure(CONFIG_FILE_LOCATION);
         String sessionFactoryJndiName = cfg.getProperty(Environment.SESSION_FACTORY_NAME);
         if (sessionFactoryJndiName != null) {
            cfg.buildSessionFactory();
            sFactory = (SessionFactory) (new InitialContext()).lookup(sessionFactoryJndiName);
         } else {
            sFactory = cfg.buildSessionFactory();
         }
      } catch (Exception e) {
         throw new HibernateException("Could not initialize the Hibernate configuration");
      }
       Session s = sFactory.getCurrentSession();
       s.close();
       Introspector.flushCaches();
       sFactory.close();
   }
   
}




Last edited by i_n_g on Wed Sep 06, 2006 2:53 pm, edited 1 time in total.

Top
 Profile  
 
 Post subject:
PostPosted: Wed Sep 06, 2006 2:49 pm 
Newbie

Joined: Wed Sep 06, 2006 2:33 pm
Posts: 13
It happens on 3.1.3 and 3.2cr4


Top
 Profile  
 
 Post subject:
PostPosted: Thu Sep 07, 2006 3:38 pm 
Newbie

Joined: Wed Sep 06, 2006 2:33 pm
Posts: 13
pop


Top
 Profile  
 
 Post subject:
PostPosted: Thu Sep 07, 2006 4:19 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 6:10 am
Posts: 8615
Location: Neuchatel, Switzerland (Danish)
...so you have created this testapp why don't you profile/debug it and figure out what is keeping it around ?

_________________
Max
Don't forget to rate


Top
 Profile  
 
 Post subject:
PostPosted: Thu Sep 07, 2006 4:30 pm 
Newbie

Joined: Wed Sep 06, 2006 2:33 pm
Posts: 13
URLClassLoader holds reference to a Proxy Class(propbably generated by ehcache), the Proxy class has lots of static fields which are java.lang.reflect.Method, the method are member of hiberante class, and these hiberenate classes are also in the URLClassLoader.

Will such a relationship keeps the classloader and classes not released?


Top
 Profile  
 
 Post subject:
PostPosted: Thu Sep 07, 2006 4:42 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 6:10 am
Posts: 8615
Location: Neuchatel, Switzerland (Danish)
btw. your test is not reproducable since you don't show what is in hibernate.cfg.xml and especially what classes you actually map.

_________________
Max
Don't forget to rate


Top
 Profile  
 
 Post subject:
PostPosted: Thu Sep 07, 2006 4:48 pm 
Newbie

Joined: Wed Sep 06, 2006 2:33 pm
Posts: 13
I don't think it does matter. But i'll be happy if i can post attchment zip of the two java projects, can i?

Code:
<?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>
      <!--define query language constants / function names-->
      
      <property name="query.substitutions">no='N', true=1, yes='Y', false=0</property>
      
      <!--DB config-->
      <property name="dialect">org.hibernate.dialect.PostgreSQLDialect</property>
      <property name="connection.driver_class">org.postgresql.Driver</property>
      <property name="connection.username">postgres</property>
      <property name="connection.password"></property>
      <property name="connection.url">jdbc:postgresql://localhost:5432/db</property>

      <property name="hibernate.cglib.use_reflection_optimizer">false</property>
      <property name="connection.useUnicode">true</property>
      <property name="connection.characterEncoding">UTF-8</property>

      <!-- Print SQL to stdout. -->
      <property name="show_sql">true</property>

      <!-- connection pool -->
      <property name="dbcp.maxActive">100</property>
      <property name="dbcp.whenExhaustedAction">1</property>
      <property name="dbcp.maxWait">120000</property>
      <property name="dbcp.maxIdle">10</property>

      <!-- prepared satement cache -->
      <property name="dbcp.ps.maxActive">100</property>   
      <property name="dbcp.ps.whenExhaustedAction">1</property>   
      <property name="dbcp.ps.maxWait">120000</property>
      <property name="dbcp.ps.maxIdle">10</property>

      <!--use a custom ConnectionProvider-->
      <property name="current_session_context_class">thread</property>
<!--      <property name="hibernate.connection.provider_class">org.hibernate.connection.DBCPConnectionProvider</property>-->
<!--      <property name="hibernate.connection.provider_class">org.hibernate.connection.ConnectionProvider</property>-->
      <!--use streams when writing binary types to / from JDBC-->
      <property name="jdbc.use_streams_for_binary">true</property>
      <!--set the maximum depth of the outer join fetch tree-->
      <property name="max_fetch_depth">1</property>
      <!--set a prefix for cache region names-->

      <!--enable the query cache-->
      <property name="cache.use_query_cache">false</property>
      <!--a Second-level Cache implementation-->
      <property name="cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
      <!--set the JDBC fetch size-->

      <property name="jdbc.fetch_size">50</property>

      <!--set the maximum JDBC 2 batch size-->

      <property name="jdbc.batch_size">100</property> 

      <!-- pkapp mapping files. -->
<!--
      <mapping resource="com/xiaodinglist/db/listrec.hbm.xml"/>
      <mapping resource="com/xiaodinglist/db/carlist.hbm.xml"/>
      <mapping resource="com/xiaodinglist/db/salelist.hbm.xml"/>
-->
   </session-factory>
</hibernate-configuration>


Top
 Profile  
 
 Post subject:
PostPosted: Thu Sep 07, 2006 4:49 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 6:10 am
Posts: 8615
Location: Neuchatel, Switzerland (Danish)
so if it doesn't matter you are telling me that if i just do this with no mappings it still "leaks" ?

_________________
Max
Don't forget to rate


Top
 Profile  
 
 Post subject:
PostPosted: Thu Sep 07, 2006 4:52 pm 
Newbie

Joined: Wed Sep 06, 2006 2:33 pm
Posts: 13
max wrote:
so if it doesn't matter you are telling me that if i just do this with no mappings it still "leaks" ?


Correct, it opens a session and closes the session, no object mappings.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Sep 07, 2006 4:53 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 6:10 am
Posts: 8615
Location: Neuchatel, Switzerland (Danish)
ok, you sparked my interest then ;)

i'll look at it.

_________________
Max
Don't forget to rate


Top
 Profile  
 
 Post subject:
PostPosted: Thu Sep 07, 2006 4:55 pm 
Newbie

Joined: Wed Sep 06, 2006 2:33 pm
Posts: 13
max wrote:
ok, you sparked my interest then ;)

i'll look at it.


thanks, I can email you the two eclipse projects.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Sep 07, 2006 5:25 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 6:10 am
Posts: 8615
Location: Neuchatel, Switzerland (Danish)
well, they just contain the code you pasted in the first posting, right ?

besides i have a feeling that it can be a very simple thing....but let me try before being too cokey ;)

_________________
Max
Don't forget to rate


Top
 Profile  
 
 Post subject:
PostPosted: Thu Sep 07, 2006 5:56 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 6:10 am
Posts: 8615
Location: Neuchatel, Switzerland (Danish)
ok so your code actually don't uses the urlclassloader...it just load the first class with it..the rest is fetched through the current thread classloader.

...and btw. i just ran this with hibernate 3.2 and don't see any issues.

all 1000 are fine..

_________________
Max
Don't forget to rate


Top
 Profile  
 
 Post subject:
PostPosted: Thu Sep 07, 2006 6:05 pm 
Newbie

Joined: Wed Sep 06, 2006 2:33 pm
Posts: 13
max wrote:
ok so your code actually don't uses the urlclassloader...it just load the first class with it..the rest is fetched through the current thread classloader.

...and btw. i just ran this with hibernate 3.2 and don't see any issues.

all 1000 are fine..
\

I have two folders, the CallJunk is loading Junk and hibernate classes from ../junk (see the code in CallJunk.java). If you put them in one java project, no leak problem. That's why i want to send you the two projects.

Create two folders "junk" and "calljunk" in same level

/junk
compile Junk.java to
/junk/bin
copy hiberante3.jar, ehcache2.1.jar, ... to
/junk/

/calljunk
Compile CallJunk.java to
/calljunk/bin

Run CallJunk in calljunk folder.


Last edited by i_n_g on Thu Sep 07, 2006 6:11 pm, edited 1 time in total.

Top
 Profile  
 
 Post subject:
PostPosted: Thu Sep 07, 2006 6:10 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 6:10 am
Posts: 8615
Location: Neuchatel, Switzerland (Danish)
ok, send them to me without the libs.

mail available under my name on the left.

_________________
Max
Don't forget to rate


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

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.