cayenne-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Andrus Adamchik <and...@objectstyle.org>
Subject Re: Memory leak of Configuration under Java 1.4, also EventManager
Date Thu, 18 Oct 2007 19:51:36 GMT
Hi Mike,

Good stuff - we need to clean it up. I was not aware of the issue  
with Configuration shutdown hook. Looking at the code, there is no  
excuse for creating it eagerly for every instance. Let me actually  
fix it now.

Regarding EventManager, this is a known issue. There is an  
EventManager.shutdown() method added in 3.0 (CAY-610) and we are  
planning to weed out a few remaining references to the default static  
EM (CAY-868) that leaks just a few threads.

Andrus


On Oct 18, 2007, at 10:41 PM, Mike Kienenberger wrote:
> For what it's worth, there's a memory leak in Configuration.  I doubt
> it will affect many people, but it was a significant contributor to
> the 1.5Gb memory requirements and 35 minutes when running my tests
> (now down to 400Mb in 25 minutes, although Velocity, StrutsTest, and
> personal memory leaks contributed some to this issue as well).
>
> The problem is that "new Thread()" without "thread.start()" under Java
> 1.4 leaks memory.
> Every new instance of Configuration creates a new Thread() without
> starting it, and since this is an inner class for Configuration,
> configuration leaks.   And that pretty much leaks the entire Cayenne
> runtime.
>
> All of my Cayenne tests create a new configuration, so this was a
> problem for me.
>
> Here's how I solved it in case anyone else has the same situation.  I
> subclassed DefaultConfiguration (which is the superclass for all of my
> other classes) as follows, and then called the "clear()" method in my
> teardown().
>
>
> public class CleanableDefaultConfiguration extends  
> DefaultConfiguration
> {
>     public CleanableDefaultConfiguration()
>     {
>         super();
>     }
>
>     public CleanableDefaultConfiguration(String  
> domainConfigurationName)
>     {
>         super(domainConfigurationName);
>     }
>
>     public void clear() {
>         uninstallConfigurationShutdownHook();
>         ((Thread)configurationShutdownHook).start();
>         try {
>             ((Thread)configurationShutdownHook).join();
>         } catch (InterruptedException e) {
>             Thread.currentThread().interrupt();
>             e.printStackTrace();
>         }
>         configurationShutdownHook = null;
>         shutdown();
>         this.setResourceLocator(null);
>         sharedConfiguration = null;
>     }
> }
>
>
> I also found issues with EventManager.   There's no public interface
> to reset it.   Here's what I ended up doing, but at some point there
> probably should be a way made to handle this with standard java code,
> and also shut down the EventManager.Dispatch threads.   Currently
> those threads run until the JVM dies, and since they are inner classes
> to EventManager, that means EventManager and its referents can't be
> garbage collected.
>
> What I did was used reflection to clear out the subjects and
> eventQueue fields, which cuts down on the impact of the leak.
>
>         // defaultManager is final -- can't reset it in java 1.4.
>         EventManager defaultManager = EventManager.getDefaultManager 
> ();
>         Field eventManagersubjectsField =
> EventManager.class.getDeclaredField("subjects");
>         eventManagersubjectsField.setAccessible(true);
>         eventManagersubjectsField.set(defaultManager,
> Collections.synchronizedMap(new WeakHashMap()));
>         Field eventManagereventQueueField =
> EventManager.class.getDeclaredField("eventQueue");
>         eventManagereventQueueField.setAccessible(true);
>         eventManagereventQueueField.set(defaultManager,
> Collections.synchronizedList(new LinkedList()));
>
>
> Again, probably not an issue for most use cases, but with 800+
> integration tests, it's an issue for me.
>


Mime
View raw message