13
13
import java .io .IOException ;
14
14
import java .util .Collection ;
15
15
import java .util .Collections ;
16
+ import java .util .ConcurrentModificationException ;
16
17
import java .util .HashMap ;
17
18
import java .util .HashSet ;
18
19
import java .util .Iterator ;
19
20
import java .util .Map ;
20
21
import java .util .Set ;
22
+ import java .util .concurrent .ConcurrentHashMap ;
21
23
22
24
import org .eclipse .core .runtime .IProgressMonitor ;
23
25
import org .eclipse .core .runtime .NullProgressMonitor ;
54
56
/**
55
57
* Simple implementation of a class hierarchy.
56
58
*
57
- * Note that this class hierarchy implementation is mutable. You can add classes via addClass(). You can add
58
- * a class even if c.getClassLoader() does not appear in getLoaders().
59
+ * Note that this class hierarchy implementation is mutable. You can add classes via addClass(). You can add a class even if
60
+ * c.getClassLoader() does not appear in getLoaders().
59
61
*/
60
62
public class ClassHierarchy implements IClassHierarchy {
61
63
@@ -69,8 +71,14 @@ public class ClassHierarchy implements IClassHierarchy {
69
71
70
72
/**
71
73
* For each {@link IClass} c in this class hierarchy, this map maps c.getReference() to the {@link Node}
74
+ *
75
+ * Note that this class provides an iterator() over this map, and that some WALA utilities (e.g. ReferenceCleanser) must iterate
76
+ * over all classes. But also note that the class hierarchy is mutable (addClass()). So, when trying to run multiple threads, we
77
+ * could see a race condition between iterator() and addClass(). With a normal {@link HashMap}, this would result in a
78
+ * {@link ConcurrentModificationException}. But with a {@link ConcurrentHashMap}, at least the code merrily chugs along,
79
+ * tolerating the race.
72
80
*/
73
- final private HashMap <TypeReference , Node > map = HashMapFactory . make ();
81
+ final private Map <TypeReference , Node > map = new ConcurrentHashMap < TypeReference , Node > ();
74
82
75
83
/**
76
84
* {@link TypeReference} for the root type
@@ -358,9 +366,6 @@ public boolean addClass(IClass klass) {
358
366
359
367
/**
360
368
* Record that a klass implements a particular interface
361
- *
362
- * @param klass
363
- * @param iface
364
369
*/
365
370
private void recordImplements (IClass klass , IClass iface ) {
366
371
Set <IClass > impls = MapUtil .findOrCreateSet (implementors , iface );
@@ -1078,7 +1083,6 @@ public AnalysisScope getScope() {
1078
1083
}
1079
1084
1080
1085
/**
1081
- * @param klass
1082
1086
* @return the number of classes that immediately extend klass. if klass is an array class A[][]...[], we return number of
1083
1087
* immediate subclasses of A. If A is primitive, we return 0.
1084
1088
*/
0 commit comments