HADOOP-8632. Configuration leaking class-loaders (Costin Leau via bobby)

git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/trunk@1376543 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Robert Joseph Evans 2012-08-23 15:24:46 +00:00
parent f909a1d4d7
commit 42beb56a2e
3 changed files with 22 additions and 7 deletions

View File

@ -426,6 +426,8 @@ Branch-2 ( Unreleased changes )
HADOOP-8721. ZKFC should not retry 45 times when attempting a graceful HADOOP-8721. ZKFC should not retry 45 times when attempting a graceful
fence during a failover. (Vinayakumar B via atm) fence during a failover. (Vinayakumar B via atm)
HADOOP-8632. Configuration leaking class-loaders (Costin Leau via bobby)
BREAKDOWN OF HDFS-3042 SUBTASKS BREAKDOWN OF HDFS-3042 SUBTASKS
HADOOP-8220. ZKFailoverController doesn't handle failure to become active HADOOP-8220. ZKFailoverController doesn't handle failure to become active

View File

@ -30,6 +30,7 @@ import java.io.OutputStream;
import java.io.OutputStreamWriter; import java.io.OutputStreamWriter;
import java.io.Reader; import java.io.Reader;
import java.io.Writer; import java.io.Writer;
import java.lang.ref.WeakReference;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.URL; import java.net.URL;
import java.util.ArrayList; import java.util.ArrayList;
@ -219,8 +220,8 @@ public class Configuration implements Iterable<Map.Entry<String,String>>,
private static final CopyOnWriteArrayList<String> defaultResources = private static final CopyOnWriteArrayList<String> defaultResources =
new CopyOnWriteArrayList<String>(); new CopyOnWriteArrayList<String>();
private static final Map<ClassLoader, Map<String, Class<?>>> private static final Map<ClassLoader, Map<String, WeakReference<Class<?>>>>
CACHE_CLASSES = new WeakHashMap<ClassLoader, Map<String, Class<?>>>(); CACHE_CLASSES = new WeakHashMap<ClassLoader, Map<String, WeakReference<Class<?>>>>();
/** /**
* Sentinel value to store negative cache results in {@link #CACHE_CLASSES}. * Sentinel value to store negative cache results in {@link #CACHE_CLASSES}.
@ -1531,28 +1532,33 @@ public class Configuration implements Iterable<Map.Entry<String,String>>,
* @return the class object, or null if it could not be found. * @return the class object, or null if it could not be found.
*/ */
public Class<?> getClassByNameOrNull(String name) { public Class<?> getClassByNameOrNull(String name) {
Map<String, Class<?>> map; Map<String, WeakReference<Class<?>>> map;
synchronized (CACHE_CLASSES) { synchronized (CACHE_CLASSES) {
map = CACHE_CLASSES.get(classLoader); map = CACHE_CLASSES.get(classLoader);
if (map == null) { if (map == null) {
map = Collections.synchronizedMap( map = Collections.synchronizedMap(
new WeakHashMap<String, Class<?>>()); new WeakHashMap<String, WeakReference<Class<?>>>());
CACHE_CLASSES.put(classLoader, map); CACHE_CLASSES.put(classLoader, map);
} }
} }
Class<?> clazz = map.get(name); Class<?> clazz = null;
WeakReference<Class<?>> ref = map.get(name);
if (ref != null) {
clazz = ref.get();
}
if (clazz == null) { if (clazz == null) {
try { try {
clazz = Class.forName(name, true, classLoader); clazz = Class.forName(name, true, classLoader);
} catch (ClassNotFoundException e) { } catch (ClassNotFoundException e) {
// Leave a marker that the class isn't found // Leave a marker that the class isn't found
map.put(name, NEGATIVE_CACHE_SENTINEL); map.put(name, new WeakReference<Class<?>>(NEGATIVE_CACHE_SENTINEL));
return null; return null;
} }
// two putters can race here, but they'll put the same class // two putters can race here, but they'll put the same class
map.put(name, clazz); map.put(name, new WeakReference<Class<?>>(clazz));
return clazz; return clazz;
} else if (clazz == NEGATIVE_CACHE_SENTINEL) { } else if (clazz == NEGATIVE_CACHE_SENTINEL) {
return null; // not found return null; // not found

View File

@ -39,6 +39,7 @@ import java.util.regex.Pattern;
import junit.framework.TestCase; import junit.framework.TestCase;
import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertNotNull;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.apache.hadoop.conf.Configuration.IntegerRanges; import org.apache.hadoop.conf.Configuration.IntegerRanges;
@ -1157,6 +1158,12 @@ public class TestConfiguration extends TestCase {
configuration.getPattern("testPattern", Pattern.compile("")).pattern()); configuration.getPattern("testPattern", Pattern.compile("")).pattern());
} }
public void testGetClassByNameOrNull() throws Exception {
Configuration config = new Configuration();
Class<?> clazz = config.getClassByNameOrNull("java.lang.Object");
assertNotNull(clazz);
}
public static void main(String[] argv) throws Exception { public static void main(String[] argv) throws Exception {
junit.textui.TestRunner.main(new String[]{ junit.textui.TestRunner.main(new String[]{
TestConfiguration.class.getName() TestConfiguration.class.getName()