From 0175c1a9c851508683dfae14e3fbe72655a5fc11 Mon Sep 17 00:00:00 2001 From: markt Date: Thu, 11 Feb 2010 20:32:09 +0000 Subject: [PATCH] Add rudimentary detection for PermGen memory leaks on web application reload. Only available via JMX for now. Next step is to add it to the manager app. git-svn-id: https://svn.apache.org/repos/asf/tomcat/trunk@909134 13f79535-47bb-0310-9956-ffa450edef68 --- java/org/apache/catalina/core/StandardHost.java | 47 +++++++++++++++++++++- .../apache/catalina/core/mbeans-descriptors.xml | 6 +++ .../apache/catalina/loader/WebappClassLoader.java | 4 ++ 3 files changed, 56 insertions(+), 1 deletion(-) diff --git a/java/org/apache/catalina/core/StandardHost.java b/java/org/apache/catalina/core/StandardHost.java index a343e6ed1..8e11dec18 100644 --- a/java/org/apache/catalina/core/StandardHost.java +++ b/java/org/apache/catalina/core/StandardHost.java @@ -19,6 +19,11 @@ package org.apache.catalina.core; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.WeakHashMap; + import javax.management.MBeanServer; import javax.management.ObjectName; @@ -27,6 +32,7 @@ import org.apache.catalina.Context; import org.apache.catalina.Host; import org.apache.catalina.LifecycleException; import org.apache.catalina.Valve; +import org.apache.catalina.loader.WebappClassLoader; import org.apache.catalina.startup.HostConfig; import org.apache.catalina.valves.ValveBase; import org.apache.tomcat.util.modeler.Registry; @@ -162,6 +168,14 @@ public class StandardHost */ private boolean createDirs = true; + + /** + * Track the class loaders for the child web applications so memory leaks + * can be detected. + */ + private Map childClassLoaders = + new WeakHashMap(); + // ------------------------------------------------------------- Properties @@ -565,11 +579,42 @@ public class StandardHost throw new IllegalArgumentException (sm.getString("standardHost.notContext")); super.addChild(child); - + + // Record a reference to the context's class loader to aid memory leak + // detection + if (child.getLoader() != null) { + childClassLoaders.put(child.getLoader().getClassLoader(), + child.getName()); + } } /** + * Attempt to identify the contexts that have a class loader memory leak. + * This is usually triggered on context reload. Note: This method attempts + * to force a full garbage collection. This should be used with extreme + * caution on a production system. + */ + public String[] findReloadedContextMemoryLeaks() { + + System.gc(); + + List result = new ArrayList(); + + for (Map.Entry entry : + childClassLoaders.entrySet()) { + ClassLoader cl = entry.getKey(); + if (cl instanceof WebappClassLoader) { + if (!((WebappClassLoader) cl).isStarted()) { + result.add(entry.getValue()); + } + } + } + + return result.toArray(new String[result.size()]); + } + + /** * Return the set of alias names for this Host. If none are defined, * a zero length array is returned. */ diff --git a/java/org/apache/catalina/core/mbeans-descriptors.xml b/java/org/apache/catalina/core/mbeans-descriptors.xml index 83eaae5ce..7e144e5f8 100644 --- a/java/org/apache/catalina/core/mbeans-descriptors.xml +++ b/java/org/apache/catalina/core/mbeans-descriptors.xml @@ -541,6 +541,12 @@ + + +