HADOOP-6881. Make WritableComparator initialize classes when looking for their raw comparator, as classes often register raw comparators in their initializer, which are no longer automatically run in Java 6 when a class is referenced. Contributed by omalley.

git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/trunk@979485 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Doug Cutting 2010-07-26 23:17:05 +00:00
parent 0d005c52ae
commit ba54f8b7e7
3 changed files with 56 additions and 3 deletions

View File

@ -151,6 +151,11 @@ Trunk (unreleased changes)
HADOOP-6536. Fixes FileUtil.fullyDelete() not to delete the contents of HADOOP-6536. Fixes FileUtil.fullyDelete() not to delete the contents of
the sym-linked directory. (Ravi Gummadi via amareshwari) the sym-linked directory. (Ravi Gummadi via amareshwari)
HADOOP-6881. Make WritableComparator intialize classes when
looking for their raw comparator, as classes often register raw
comparators in initializers, which are no longer automatically run
in Java 6 when a class is referenced. (cutting via omalley)
Release 0.21.0 - Unreleased Release 0.21.0 - Unreleased
INCOMPATIBLE CHANGES INCOMPATIBLE CHANGES

View File

@ -42,13 +42,38 @@ public class WritableComparator implements RawComparator {
new HashMap<Class, WritableComparator>(); // registry new HashMap<Class, WritableComparator>(); // registry
/** Get a comparator for a {@link WritableComparable} implementation. */ /** Get a comparator for a {@link WritableComparable} implementation. */
public static synchronized WritableComparator get(Class<? extends WritableComparable> c) { public static synchronized
WritableComparator get(Class<? extends WritableComparable> c) {
WritableComparator comparator = comparators.get(c); WritableComparator comparator = comparators.get(c);
if (comparator == null) if (comparator == null) {
comparator = new WritableComparator(c, true); // force the static initializers to run
forceInit(c);
// look to see if it is defined now
comparator = comparators.get(c);
// if not, use the generic one
if (comparator == null) {
comparator = new WritableComparator(c, true);
comparators.put(c, comparator);
}
}
return comparator; return comparator;
} }
/**
* Force initialization of the static members.
* As of Java 5, referencing a class doesn't force it to initialize. Since
* this class requires that the classes be initialized to declare their
* comparators, we force that initialization to happen.
* @param cls the class to initialize
*/
private static void forceInit(Class<?> cls) {
try {
Class.forName(cls.getName(), true, cls.getClassLoader());
} catch (ClassNotFoundException e) {
throw new IllegalArgumentException("Can't initialize class " + cls, e);
}
}
/** Register an optimized comparator for a {@link WritableComparable} /** Register an optimized comparator for a {@link WritableComparable}
* implementation. */ * implementation. */
public static synchronized void define(Class c, public static synchronized void define(Class c,

View File

@ -96,4 +96,27 @@ public static Writable testWritable(Writable before
return after; return after;
} }
private static class FrobComparator extends WritableComparator {
public FrobComparator() { super(Frob.class); }
@Override public int compare(byte[] b1, int s1, int l1,
byte[] b2, int s2, int l2) {
return 0;
}
}
private static class Frob implements WritableComparable {
static { // register default comparator
WritableComparator.define(Frob.class, new FrobComparator());
}
@Override public void write(DataOutput out) throws IOException {}
@Override public void readFields(DataInput in) throws IOException {}
@Override public int compareTo(Object o) { return 0; }
}
/** Test that comparator is defined. */
public static void testGetComparator() throws Exception {
assert(WritableComparator.get(Frob.class) instanceof FrobComparator);
}
} }