Browse Source

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 <matthias.sohn@sap.com>
stable-4.10
Matthias Sohn 7 years ago
parent
commit
95fc2b210f
  1. 26
      org.eclipse.jgit/src/org/eclipse/jgit/nls/NLS.java

26
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<NLS> local = new InheritableThreadLocal<NLS>() {
@Override
protected NLS initialValue() {
return new NLS(Locale.getDefault());
}
};
private static final InheritableThreadLocal<NLS> 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.
* <p>
* Semantically this is equivalent to <code>NLS.setLocale(Locale.getDefault())</code>.
* Semantically this is equivalent to
* <code>NLS.setLocale(Locale.getDefault())</code>.
*/
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 extends TranslationBundle> T getBundleFor(Class<T> type) {
return local.get().get(type);
NLS b = local.get();
if (b == null) {
b = useJVMDefaultInternal();
}
return b.get(type);
}
final private Locale locale;

Loading…
Cancel
Save