From 4219f17597f6d54bc9943b5363962d7078fc8ba5 Mon Sep 17 00:00:00 2001 From: Robert Joseph Evans Date: Thu, 23 Aug 2012 15:26:42 +0000 Subject: [PATCH] svn merge -c 1376543 FIXES: HADOOP-8632. Configuration leaking class-loaders (Costin Leau via bobby) git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/branches/branch-2@1376546 13f79535-47bb-0310-9956-ffa450edef68 --- .../hadoop-common/CHANGES.txt | 2 ++ .../org/apache/hadoop/conf/Configuration.java | 20 ++++++++++++------- .../apache/hadoop/conf/TestConfiguration.java | 7 +++++++ 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/hadoop-common-project/hadoop-common/CHANGES.txt b/hadoop-common-project/hadoop-common/CHANGES.txt index 35bdcdcf4bd..d8f17a63b13 100644 --- a/hadoop-common-project/hadoop-common/CHANGES.txt +++ b/hadoop-common-project/hadoop-common/CHANGES.txt @@ -219,6 +219,8 @@ Release 2.0.1-alpha - UNRELEASED HADOOP-8721. ZKFC should not retry 45 times when attempting a graceful fence during a failover. (Vinayakumar B via atm) + HADOOP-8632. Configuration leaking class-loaders (Costin Leau via bobby) + BREAKDOWN OF HDFS-3042 SUBTASKS HADOOP-8220. ZKFailoverController doesn't handle failure to become active diff --git a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/conf/Configuration.java b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/conf/Configuration.java index 5076b9efba3..319e537abe5 100644 --- a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/conf/Configuration.java +++ b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/conf/Configuration.java @@ -30,6 +30,7 @@ import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.Reader; import java.io.Writer; +import java.lang.ref.WeakReference; import java.net.InetSocketAddress; import java.net.URL; import java.util.ArrayList; @@ -219,8 +220,8 @@ public class Configuration implements Iterable>, private static final CopyOnWriteArrayList defaultResources = new CopyOnWriteArrayList(); - private static final Map>> - CACHE_CLASSES = new WeakHashMap>>(); + private static final Map>>> + CACHE_CLASSES = new WeakHashMap>>>(); /** * Sentinel value to store negative cache results in {@link #CACHE_CLASSES}. @@ -1495,28 +1496,33 @@ public class Configuration implements Iterable>, * @return the class object, or null if it could not be found. */ public Class getClassByNameOrNull(String name) { - Map> map; + Map>> map; synchronized (CACHE_CLASSES) { map = CACHE_CLASSES.get(classLoader); if (map == null) { map = Collections.synchronizedMap( - new WeakHashMap>()); + new WeakHashMap>>()); CACHE_CLASSES.put(classLoader, map); } } - Class clazz = map.get(name); + Class clazz = null; + WeakReference> ref = map.get(name); + if (ref != null) { + clazz = ref.get(); + } + if (clazz == null) { try { clazz = Class.forName(name, true, classLoader); } catch (ClassNotFoundException e) { // Leave a marker that the class isn't found - map.put(name, NEGATIVE_CACHE_SENTINEL); + map.put(name, new WeakReference>(NEGATIVE_CACHE_SENTINEL)); return null; } // two putters can race here, but they'll put the same class - map.put(name, clazz); + map.put(name, new WeakReference>(clazz)); return clazz; } else if (clazz == NEGATIVE_CACHE_SENTINEL) { return null; // not found diff --git a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/conf/TestConfiguration.java b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/conf/TestConfiguration.java index b227badd2b9..ec58f20177a 100644 --- a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/conf/TestConfiguration.java +++ b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/conf/TestConfiguration.java @@ -39,6 +39,7 @@ import java.util.regex.Pattern; import junit.framework.TestCase; import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertNotNull; import org.apache.commons.lang.StringUtils; import org.apache.hadoop.conf.Configuration.IntegerRanges; @@ -1042,6 +1043,12 @@ public class TestConfiguration extends TestCase { } } + 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 { junit.textui.TestRunner.main(new String[]{ TestConfiguration.class.getName()