LOG4J2-1176 use weak reference to classloader in Provider to prevent memory leaks when web app is unloaded
Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/09786243 Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/09786243 Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/09786243 Branch: refs/heads/LOG4J2-89 Commit: 097862436670c759a7a977f3eb93d17e24c37d18 Parents: 96e3f4d Author: rpopma <[email protected]> Authored: Sun Nov 8 15:38:19 2015 +0900 Committer: Ralph Goers <[email protected]> Committed: Fri Nov 20 17:39:20 2015 -0700 ---------------------------------------------------------------------- .../org/apache/logging/log4j/spi/Provider.java | 40 ++++++++++++++++++-- 1 file changed, 36 insertions(+), 4 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/09786243/log4j-api/src/main/java/org/apache/logging/log4j/spi/Provider.java ---------------------------------------------------------------------- diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/spi/Provider.java b/log4j-api/src/main/java/org/apache/logging/log4j/spi/Provider.java index cd54d43..f5c9f48 100644 --- a/log4j-api/src/main/java/org/apache/logging/log4j/spi/Provider.java +++ b/log4j-api/src/main/java/org/apache/logging/log4j/spi/Provider.java @@ -16,6 +16,7 @@ */ package org.apache.logging.log4j.spi; +import java.lang.ref.WeakReference; import java.net.URL; import java.util.Properties; @@ -48,11 +49,11 @@ public class Provider { private final String className; private final String threadContextMap; private final URL url; - private final ClassLoader classLoader; + private final WeakReference<ClassLoader> classLoader; public Provider(final Properties props, final URL url, final ClassLoader classLoader) { this.url = url; - this.classLoader = classLoader; + this.classLoader = new WeakReference<ClassLoader>(classLoader); final String weight = props.getProperty(FACTORY_PRIORITY); priority = weight == null ? DEFAULT_PRIORITY : Integer.valueOf(weight); className = props.getProperty(LOGGER_CONTEXT_FACTORY); @@ -87,8 +88,12 @@ public class Provider { if (className == null) { return null; } + ClassLoader loader = classLoader.get(); + if (loader == null) { + return null; + } try { - final Class<?> clazz = classLoader.loadClass(className); + final Class<?> clazz = loader.loadClass(className); if (LoggerContextFactory.class.isAssignableFrom(clazz)) { return clazz.asSubclass(LoggerContextFactory.class); } @@ -116,8 +121,12 @@ public class Provider { if (threadContextMap == null) { return null; } + ClassLoader loader = classLoader.get(); + if (loader == null) { + return null; + } try { - final Class<?> clazz = classLoader.loadClass(threadContextMap); + final Class<?> clazz = loader.loadClass(threadContextMap); if (ThreadContextMap.class.isAssignableFrom(clazz)) { return clazz.asSubclass(ThreadContextMap.class); } @@ -135,4 +144,27 @@ public class Provider { public URL getUrl() { return url; } + + @Override + public String toString() { + String result = "Provider["; + if (priority != DEFAULT_PRIORITY) { + result += "priority=" + priority + ", "; + } + if (threadContextMap != null) { + result += "threadContextMap=" + threadContextMap + ", "; + } + if (className != null) { + result += "className=" + className + ", "; + } + result += "url=" + url; + final ClassLoader loader = classLoader.get(); + if (loader == null) { + result += ", classLoader=null(not reachable)"; + } else { + result += ", classLoader=" + loader; + } + result += "]"; + return result; + } }
