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:
parent
f909a1d4d7
commit
42beb56a2e
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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()
|
||||||
|
|
Loading…
Reference in New Issue