You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by ja...@apache.org on 2010/10/28 12:48:27 UTC
svn commit: r1028255 - in
/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces:
view/facelets/tag/MetaRulesetImpl.java webapp/AbstractFacesInitializer.java
Author: jakobk
Date: Thu Oct 28 10:48:26 2010
New Revision: 1028255
URL: http://svn.apache.org/viewvc?rev=1028255&view=rev
Log:
MYFACES-2942 Memory Leak in MyFaces 2.0.1 probably as well in 2.0.2 (use static WeakHashMap<ClassLoader, Map<String, MetadataTarget>> as cache and do a cleanup upon undeploy)
Modified:
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/MetaRulesetImpl.java
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/webapp/AbstractFacesInitializer.java
Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/MetaRulesetImpl.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/MetaRulesetImpl.java?rev=1028255&r1=1028254&r2=1028255&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/MetaRulesetImpl.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/MetaRulesetImpl.java Thu Oct 28 10:48:26 2010
@@ -18,9 +18,9 @@
*/
package org.apache.myfaces.view.facelets.tag;
+import org.apache.myfaces.shared_impl.util.ClassUtils;
import org.apache.myfaces.view.facelets.util.ParameterCheck;
-import javax.faces.context.FacesContext;
import javax.faces.view.facelets.FaceletContext;
import javax.faces.view.facelets.MetaRule;
import javax.faces.view.facelets.MetaRuleset;
@@ -34,6 +34,7 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.WeakHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -49,22 +50,35 @@ public final class MetaRulesetImpl exten
//private final static Logger log = Logger.getLogger("facelets.tag.meta");
private final static Logger log = Logger.getLogger(MetaRulesetImpl.class.getName());
- private static final String METADATA_KEY
- = "org.apache.myfaces.view.facelets.tag.MetaRulesetImpl.METADATA";
+ /**
+ * Cache the MetadataTarget instances per ClassLoader using the Class-Name of the type variable
+ * of MetadataTarget.
+ * NOTE that we do it this way, because the only other valid way in order to support a shared
+ * classloader scenario would be to use a WeakHashMap<Class<?>, MetadataTarget>, but this
+ * creates a cyclic reference between the key and the value of the WeakHashMap which will
+ * most certainly cause a memory leak! Furthermore we can manually cleanup the Map when
+ * the webapp is undeployed just by removing the Map for the current ClassLoader.
+ */
+ private final static WeakHashMap<ClassLoader, Map<String, MetadataTarget>> _metadata
+ = new WeakHashMap<ClassLoader, Map<String, MetadataTarget>>();
+
+ /**
+ * Removes the cached MetadataTarget instances in order to prevent a memory leak.
+ */
+ public static void clearMetadataTargetCache()
+ {
+ _metadata.remove(ClassUtils.getContextClassLoader());
+ }
private static Map<String, MetadataTarget> getMetaData()
{
- FacesContext facesContext = FacesContext.getCurrentInstance();
- Map<String, Object> applicationMap = facesContext
- .getExternalContext().getApplicationMap();
-
- Map<String, MetadataTarget> metadata =
- (Map<String, MetadataTarget>) applicationMap.get(METADATA_KEY);
+ Map<String, MetadataTarget> metadata = (Map<String, MetadataTarget>)
+ _metadata.get(ClassUtils.getContextClassLoader());
if (metadata == null)
{
metadata = new HashMap<String, MetadataTarget>();
- applicationMap.put(METADATA_KEY, metadata);
+ _metadata.put(ClassUtils.getContextClassLoader(), metadata);
}
return metadata;
Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/webapp/AbstractFacesInitializer.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/webapp/AbstractFacesInitializer.java?rev=1028255&r1=1028254&r2=1028255&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/webapp/AbstractFacesInitializer.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/webapp/AbstractFacesInitializer.java Thu Oct 28 10:48:26 2010
@@ -31,6 +31,7 @@ import org.apache.myfaces.shared_impl.co
import org.apache.myfaces.shared_impl.util.StateUtils;
import org.apache.myfaces.shared_impl.util.WebConfigParamUtils;
import org.apache.myfaces.shared_impl.webapp.webxml.WebXml;
+import org.apache.myfaces.view.facelets.tag.MetaRulesetImpl;
import javax.el.ExpressionFactory;
import javax.faces.application.Application;
@@ -272,6 +273,9 @@ public abstract class AbstractFacesIniti
_dispatchApplicationEvent(servletContext, PreDestroyApplicationEvent.class);
+ // clear the cache of MetaRulesetImpl in order to prevent a memory leak
+ MetaRulesetImpl.clearMetadataTargetCache();
+
// TODO is it possible to make a real cleanup?
}