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/60dd2265 Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/60dd2265 Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/60dd2265 Branch: refs/heads/LOG4J-1181 Commit: 60dd22656e106d8476cca70c17475917bb8cf744 Parents: 83c2247 Author: rpopma <rpo...@apache.org> Authored: Sun Nov 8 15:38:19 2015 +0900 Committer: rpopma <rpo...@apache.org> Committed: Sun Nov 8 15:38:19 2015 +0900 ---------------------------------------------------------------------- .../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/60dd2265/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; + } }