[ http://issues.apache.org/jira/browse/GERONIMO-1118?page=all ]

Kevan Miller updated GERONIMO-1118:
-----------------------------------

    Attachment: IntrospectorFix.patch

Thanks Dain. Works great. Attached fix calls Introspector.flushCaches() during 
destroy. We could make this behavior configurable. Default to call 
flushCaches(), but allow this behavior to be inhibited. I just don't see much 
reason to add the complexity. I don't think there's much caching going on...

Unfortunately, we're not out-of-the-woods, yet. We're freeing up some of our 
MultiParentClassLoaders, but not all. We're currently holding on to 2 class 
loaders per deploy/undeploy cycle.

Current culprits are: 

Axis -- o.a.a.utils.JavaUtils.enumMap is a HashMap which is holding onto some 
Classes. Looks like making this a WeakHashMap would fix the problem.
Axis -- o.a.a.utils.TypeDesc (looks like this was fixed by Axis between 
1.3_Snapshot and 1.3. I'll be confirming...)
Geronimo -- o.a.g.connector.outbound.TCCLInterceptor is being maintained in a 
list of ConnectionInterceptors. Need to figure out when it should be removed 
from the list...

I'll be working on addressing the above problems in separate Jira issues.

> memory leak deploying web services caused by 
> java.bean.Introspector.getBeanInfo()
> ---------------------------------------------------------------------------------
>
>          Key: GERONIMO-1118
>          URL: http://issues.apache.org/jira/browse/GERONIMO-1118
>      Project: Geronimo
>         Type: Bug
>   Components: webservices
>     Versions: 1.0
>  Environment: Sun JDK 1.4.2/Win XP
>     Reporter: Kevan Miller
>  Attachments: IntrospectorFix.patch
>
> If you deploy and undeploy DayTrader several times, your server will run out 
> of Permanent Generation space. I've tracked down a problem which is caused by 
> java.bean.Introspector (there may be other problems, but it's hard to tell 
> until this problem is fixed). The basic problem is described here -- 
> http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5102804.
> To summarize, the static method java.bean.Introspector.getBeanInfo(Class) 
> computes a BeanInfo object to describe the given Class. The computed BeanInfo 
> data is cached in a WeakHashMap called "beanInfoCache". There's one fatal 
> flaw in this approach. There's nothing "weak" at all about beanInfoCache. The 
> key for the Map is the Class object. The value object is the BeanInfo data. 
> Unfortunately, the BeanInfo data strongly references the Class. This strong 
> reference will prevent the Class from being identified as available for GC 
> via the WeakHashMap.
> Since java.bean.Introspector is loaded by the system class loader (and is 
> thus a GC root), this means that Bean classes (e.g. 
> org.apache.geronimo.samples.daytrader.client.ws.AccountDataBean), their 
> MultiParentClassLoader, and all classes loaded by the MultiParentClassLoader 
> will be kept alive until you kill your server...
> Luckily (or because of this problem?), Introspector also has flushCaches() 
> and flushFromCaches(Class) methods which perform predictable functions. 
> Several projects, including Tomcat and Spring, use these methods to prevent 
> Introspector from causing memory leaks in their environments.
> Geronimo has the following usages of getBeanInfo()
> axis-builder/src/java/org/apache/geronimo/axis/builder/HeavyweightTypeInfoBuilder.java:389
> axis-builder/src/java/org/apache/geronimo/axis/builder/LightweightTypeInfoBuilder.java:131
> service-builder/src/java/org/apache/geronimo/deployment/service/JavaBeanXmlAttributeBuilder.java:66
> A non-scientific search (e.g. I don't have all the source), showed calls to 
> Introspector.getBeanInfo() by the following projects:
> axis, cglib, commons-collections, tomcat (but calls flushCache), log4j 
> I've thought of the following options for fixing this problem (alternative 
> proposals welcome):
> 1. Follow all calls to getBeanInfo(Class) with a flushFromCaches(Class). This 
> seems fragile and impractical (we can't insure that other projects/apps 
> follow this rule). 
> 2. Force java.Bean.Introspector to be loaded by MultiParentClassLoader. This 
> would prevent the Introspector class from being a GC root. Would work, but is 
> counter to the current class loader implementation...
> 3. Call Introspector.flushCaches() at appropriate times (i.e. when a 
> ClassLoader is going out of scope -- when a GBean is stopped?). I need a 
> little help here in knowing when/where this should be... Although this is a 
> bit heavy-handed, it seems like a safe approach.
> 4. (just thought of this one). Instead of calling flushCaches() as described 
> in 3, we could instead loop through all classes loaded by the appropriate 
> MultiParentClassLoaders and call flushFromCaches(Class) (or a subset of the 
> classes). This would work, but doesn't seem necessary. I doubt we have very 
> much caching going on...
> I'll work on 3 and see how things improve...

-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
   http://issues.apache.org/jira/secure/Administrators.jspa
-
For more information on JIRA, see:
   http://www.atlassian.com/software/jira

Reply via email to