Index: working_classlib/modules/luni/src/main/java/java/io/ObjectStreamClass.java =================================================================== --- working_classlib/modules/luni/src/main/java/java/io/ObjectStreamClass.java (revision 645620) +++ working_classlib/modules/luni/src/main/java/java/io/ObjectStreamClass.java (working copy) @@ -17,6 +17,7 @@ package java.io; +import java.lang.ref.SoftReference; import java.lang.ref.WeakReference; import java.lang.reflect.Constructor; import java.lang.reflect.Field; @@ -30,7 +31,7 @@ import java.util.Arrays; import java.util.Comparator; import java.util.List; -import java.util.WeakHashMap; +import java.util.HashMap; import org.apache.harmony.luni.util.Msg; import org.apache.harmony.luni.util.PriviAction; @@ -137,7 +138,7 @@ // Table mapping instances of java.lang.Class to to corresponding instances // of ObjectStreamClass - private static final WeakHashMap, ObjectStreamClass> classesAndDescriptors = new WeakHashMap, ObjectStreamClass>(); + private static final HashMap, SoftReference> classesAndDescriptors = new HashMap, SoftReference>(); private transient Method methodWriteReplace; @@ -928,18 +929,33 @@ */ private static ObjectStreamClass lookupStreamClass(Class cl, boolean computeSUID) { - // Synchronized because of the lookup table 'classesAndDescriptors' ObjectStreamClass cachedValue; - synchronized (classesAndDescriptors) { - cachedValue = classesAndDescriptors.get(cl); - if (cachedValue == null) { - cachedValue = createClassDesc(cl, computeSUID); - classesAndDescriptors.put(cl, cachedValue); - } - } + SoftReference reference; + + // 1. try unsynchronized first + // 2. SoftReference is better than WeakReference here since + // it will be freed on memory exhaustion only + + // fastpath: lookup the reference + reference = classesAndDescriptors.get(cl); + if (reference != null) { + cachedValue = reference.get(); + if (cachedValue != null) { + return cachedValue; + } + } + + // slowpath: no entry was found or it was deleted + // it does not matter whether we will return the duplicate, + // so we need not to look up again, just create OSC and store it + synchronized(classesAndDescriptors) { + cachedValue = createClassDesc(cl, computeSUID); + reference = new SoftReference(cachedValue); + classesAndDescriptors.put(cl, reference); + } + return cachedValue; - } /**