Author: jlowe Date: Wed Jan 16 21:26:04 2013 New Revision: 1434412 URL: http://svn.apache.org/viewvc?rev=1434412&view=rev Log: svn merge -c 1303634 FIXES: HADOOP-8157. Fix race condition in Configuration that could cause spurious ClassNotFoundExceptions after a GC. Contributed by Todd Lipcon.
Modified: hadoop/common/branches/branch-0.23/hadoop-common-project/hadoop-common/CHANGES.txt hadoop/common/branches/branch-0.23/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/conf/Configuration.java Modified: hadoop/common/branches/branch-0.23/hadoop-common-project/hadoop-common/CHANGES.txt URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-0.23/hadoop-common-project/hadoop-common/CHANGES.txt?rev=1434412&r1=1434411&r2=1434412&view=diff ============================================================================== --- hadoop/common/branches/branch-0.23/hadoop-common-project/hadoop-common/CHANGES.txt (original) +++ hadoop/common/branches/branch-0.23/hadoop-common-project/hadoop-common/CHANGES.txt Wed Jan 16 21:26:04 2013 @@ -12,6 +12,9 @@ Release 0.23.7 - UNRELEASED BUG FIXES + HADOOP-8157. Fix race condition in Configuration that could cause spurious + ClassNotFoundExceptions after a GC. (todd) + Release 0.23.6 - UNRELEASED INCOMPATIBLE CHANGES Modified: hadoop/common/branches/branch-0.23/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/conf/Configuration.java URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-0.23/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/conf/Configuration.java?rev=1434412&r1=1434411&r2=1434412&view=diff ============================================================================== --- hadoop/common/branches/branch-0.23/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/conf/Configuration.java (original) +++ hadoop/common/branches/branch-0.23/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/conf/Configuration.java Wed Jan 16 21:26:04 2013 @@ -223,6 +223,12 @@ public class Configuration implements It CACHE_CLASSES = new WeakHashMap<ClassLoader, Map<String, Class<?>>>(); /** + * Sentinel value to store negative cache results in {@link #CACHE_CLASSES}. + */ + private static final Class<?> NEGATIVE_CACHE_SENTINEL = + NegativeCacheSentinel.class; + + /** * Stores the mapping of key to the resource which modifies or loads * the key most recently */ @@ -1474,24 +1480,24 @@ public class Configuration implements It } } - Class<?> clazz = null; - if (!map.containsKey(name)) { + Class<?> clazz = map.get(name); + if (clazz == null) { try { clazz = Class.forName(name, true, classLoader); } catch (ClassNotFoundException e) { - map.put(name, null); //cache negative that class is not found + // Leave a marker that the class isn't found + map.put(name, NEGATIVE_CACHE_SENTINEL); return null; } // two putters can race here, but they'll put the same class map.put(name, clazz); - } else { // check already performed on this class name - clazz = map.get(name); - if (clazz == null) { // found the negative - return null; - } + return clazz; + } else if (clazz == NEGATIVE_CACHE_SENTINEL) { + return null; // not found + } else { + // cache hit + return clazz; } - - return clazz; } /** @@ -2248,4 +2254,10 @@ public class Configuration implements It Configuration.addDeprecation("dfs.umaskmode", new String[]{CommonConfigurationKeys.FS_PERMISSIONS_UMASK_KEY}); } + + /** + * A unique class which is used as a sentinel value in the caching + * for getClassByName. {@see Configuration#getClassByNameOrNull(String)} + */ + private static abstract class NegativeCacheSentinel {} }