From 95fc2b210f3df3a1ff5c729dbc0624e3d25d34bd Mon Sep 17 00:00:00 2001 From: Matthias Sohn Date: Mon, 8 Jan 2018 10:40:23 +0100 Subject: [PATCH] Don't subclass ThreadLocal to avoid memory leak in NLS These problem usually occur when you subclass ThreadLocal (usually to implement initialValue). Those classes reference the webapp's classloader. The ThreadLocal subclass in turn is referenced by each Thread instance (that's how ThreadLocals are implemented, they have a "helper-Map" in each Thread instance, so the leak is actually not a tiny Random instance but the whole webapp's classloader with a bunch of class definitions and statically referenced parts of the webapp. Bug: 449321 Change-Id: Ie7a8b0b90e40229e2471202f2a12637b9e0b1d11 Signed-off-by: Matthias Sohn --- .../src/org/eclipse/jgit/nls/NLS.java | 26 ++++++++++++------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/nls/NLS.java b/org.eclipse.jgit/src/org/eclipse/jgit/nls/NLS.java index 3c0d839dfb..89a87af9eb 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/nls/NLS.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/nls/NLS.java @@ -74,12 +74,7 @@ public class NLS { */ public static final Locale ROOT_LOCALE = new Locale("", "", ""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - private static final InheritableThreadLocal local = new InheritableThreadLocal() { - @Override - protected NLS initialValue() { - return new NLS(Locale.getDefault()); - } - }; + private static final InheritableThreadLocal local = new InheritableThreadLocal<>(); /** * Sets the locale for the calling thread. @@ -99,10 +94,19 @@ public class NLS { /** * Sets the JVM default locale as the locale for the calling thread. *

- * Semantically this is equivalent to NLS.setLocale(Locale.getDefault()). + * Semantically this is equivalent to + * NLS.setLocale(Locale.getDefault()). */ public static void useJVMDefaultLocale() { - local.set(new NLS(Locale.getDefault())); + useJVMDefaultInternal(); + } + + // TODO(ms): change signature of public useJVMDefaultLocale() in 5.0 to get + // rid of this internal method + private static NLS useJVMDefaultInternal() { + NLS b = new NLS(Locale.getDefault()); + local.set(b); + return b; } /** @@ -122,7 +126,11 @@ public class NLS { * {@link org.eclipse.jgit.errors.TranslationStringMissingException} */ public static T getBundleFor(Class type) { - return local.get().get(type); + NLS b = local.get(); + if (b == null) { + b = useJVMDefaultInternal(); + } + return b.get(type); } final private Locale locale; -- 2.39.5