11
11
*******************************************************************************/
12
12
package com .ibm .wala .examples .analysis ;
13
13
14
- import java .io .File ;
15
- import java .io .IOException ;
16
- import java .util .Collection ;
17
- import java .util .Iterator ;
18
- import java .util .Properties ;
19
- import java .util .Set ;
20
- import java .util .jar .JarFile ;
21
-
22
14
import com .ibm .wala .classLoader .ArrayClass ;
23
15
import com .ibm .wala .classLoader .IClass ;
24
16
import com .ibm .wala .classLoader .IField ;
46
38
import com .ibm .wala .util .WalaException ;
47
39
import com .ibm .wala .util .collections .HashSetFactory ;
48
40
import com .ibm .wala .util .intset .OrdinalSet ;
41
+ import java .io .File ;
42
+ import java .io .IOException ;
43
+ import java .util .Collection ;
44
+ import java .util .Iterator ;
45
+ import java .util .Properties ;
46
+ import java .util .Set ;
47
+ import java .util .jar .JarFile ;
49
48
50
49
/**
51
- * <P>
52
- * A simple thread-level escape analysis: this code computes the set of classes of which some instance may be accessed
53
- * by some thread other than the one that created it.
54
- * </P>
55
- *
56
- * <P>
57
- * The algorithm is not very bright; it is based on the observation that there are only three ways for an object to pass
58
- * from one thread to another.
50
+ * A simple thread-level escape analysis: this code computes the set of classes of which some
51
+ * instance may be accessed by some thread other than the one that created it.
52
+ *
53
+ * <p>The algorithm is not very bright; it is based on the observation that there are only three
54
+ * ways for an object to pass from one thread to another.
55
+ *
59
56
* <UL>
60
- * <LI> The object is stored into a static variable.
61
- * <LI> The object is stored into an instance field of a Thread
62
- * <LI> The object is reachable from a field of another escaping object.
57
+ * <LI>The object is stored into a static variable.
58
+ * <LI>The object is stored into an instance field of a Thread
59
+ * <LI>The object is reachable from a field of another escaping object.
63
60
* </UL>
64
- * </P>
65
- *
66
- * <P>
67
- * This observation is implemented in the obvious way:
61
+ *
62
+ * <p>This observation is implemented in the obvious way:
63
+ *
68
64
* <OL>
69
- * <LI> All static fields are collected
70
- * <LI> All Thread constructor parameters are collected
71
- * <LI> The points-to sets of these values represent the base set of escapees.
72
- * <LI> All object reachable from fields of these objects are added
73
- * <LI> This process continues until a fixpoint is reached
74
- * <LI> The abstract objects in the points-to sets are converted to types
75
- * <LI> This set of types is returned
65
+ * <LI>All static fields are collected
66
+ * <LI>All Thread constructor parameters are collected
67
+ * <LI>The points-to sets of these values represent the base set of escapees.
68
+ * <LI>All object reachable from fields of these objects are added
69
+ * <LI>This process continues until a fixpoint is reached
70
+ * <LI>The abstract objects in the points-to sets are converted to types
71
+ * <LI>This set of types is returned
76
72
* </OL>
77
- * </P>
78
- *
73
+ *
79
74
* @author Julian Dolby
80
75
*/
81
76
public class SimpleThreadEscapeAnalysis extends AbstractAnalysisEngine {
@@ -85,7 +80,8 @@ public class SimpleThreadEscapeAnalysis extends AbstractAnalysisEngine {
85
80
private final String applicationMainClass ;
86
81
87
82
/**
88
- * The two input parameters define the program to analyze: the jars of .class files and the main class to start from.
83
+ * The two input parameters define the program to analyze: the jars of .class files and the main
84
+ * class to start from.
89
85
*/
90
86
public SimpleThreadEscapeAnalysis (Set <JarFile > applicationJarFiles , String applicationMainClass ) {
91
87
this .applicationJarFiles = applicationJarFiles ;
@@ -94,12 +90,13 @@ public SimpleThreadEscapeAnalysis(Set<JarFile> applicationJarFiles, String appli
94
90
95
91
@ Override
96
92
protected CallGraphBuilder getCallGraphBuilder (
97
- IClassHierarchy cha , AnalysisOptions options , IAnalysisCacheView cache ) {
93
+ IClassHierarchy cha , AnalysisOptions options , IAnalysisCacheView cache ) {
98
94
return Util .makeZeroCFABuilder (Language .JAVA , options , cache , cha , scope );
99
95
}
100
96
101
97
/**
102
- * Given a root path, add it to the set if it is a jar, or traverse it recursively if it is a directory.
98
+ * Given a root path, add it to the set if it is a jar, or traverse it recursively if it is a
99
+ * directory.
103
100
*/
104
101
private void collectJars (File f , Set <JarFile > result ) throws IOException {
105
102
if (f .isDirectory ()) {
@@ -114,9 +111,7 @@ private void collectJars(File f, Set<JarFile> result) throws IOException {
114
111
}
115
112
}
116
113
117
- /**
118
- * Collect the set of JarFiles that constitute the system libraries of the running JRE.
119
- */
114
+ /** Collect the set of JarFiles that constitute the system libraries of the running JRE. */
120
115
private JarFile [] getSystemJars () throws IOException {
121
116
String javaHomePath = "garbage" ;
122
117
Set <JarFile > jarFiles = HashSetFactory .make ();
@@ -148,12 +143,12 @@ private JarFile[] getSystemJars() throws IOException {
148
143
}
149
144
150
145
/**
151
- * Take the given set of JarFiles that constitute the program, and return a set of Module files as expected by the
152
- * WALA machinery.
146
+ * Take the given set of JarFiles that constitute the program, and return a set of Module files as
147
+ * expected by the WALA machinery.
153
148
*/
154
149
private Set <JarFileModule > getModuleFiles () {
155
150
Set <JarFileModule > result = HashSetFactory .make ();
156
- for (Iterator <JarFile > jars = applicationJarFiles .iterator (); jars .hasNext ();) {
151
+ for (Iterator <JarFile > jars = applicationJarFiles .iterator (); jars .hasNext (); ) {
157
152
result .add (new JarFileModule (jars .next ()));
158
153
}
159
154
@@ -162,11 +157,12 @@ private Set<JarFileModule> getModuleFiles() {
162
157
163
158
/**
164
159
* The heart of the analysis.
160
+ *
165
161
* @throws CancelException
166
162
* @throws IllegalArgumentException
167
163
*/
168
- public Set <IClass > gatherThreadEscapingClasses () throws IOException , ClassHierarchyException , IllegalArgumentException ,
169
- CancelException {
164
+ public Set <IClass > gatherThreadEscapingClasses ()
165
+ throws IOException , ClassHierarchyException , IllegalArgumentException , CancelException {
170
166
171
167
//
172
168
// set the application to analyze
@@ -226,7 +222,7 @@ public Set<IClass> gatherThreadEscapingClasses() throws IOException, ClassHierar
226
222
// 1) static fields
227
223
for (IClass cls : cha ) {
228
224
Collection <IField > staticFields = cls .getDeclaredStaticFields ();
229
- for (Iterator <IField > sfs = staticFields .iterator (); sfs .hasNext ();) {
225
+ for (Iterator <IField > sfs = staticFields .iterator (); sfs .hasNext (); ) {
230
226
IField sf = sfs .next ();
231
227
if (sf .getFieldTypeReference ().isReferenceType ()) {
232
228
escapeAnalysisRoots .add (heapModel .getPointerKeyForStaticField (sf ));
@@ -240,21 +236,21 @@ public Set<IClass> gatherThreadEscapingClasses() throws IOException, ClassHierar
240
236
// reachable from fields of types in these pointer keys, and all
241
237
// Thread objects must be constructed somewhere)
242
238
Collection <IClass > threads = cha .computeSubClasses (TypeReference .JavaLangThread );
243
- for (Iterator <IClass > clss = threads .iterator (); clss .hasNext ();) {
239
+ for (Iterator <IClass > clss = threads .iterator (); clss .hasNext (); ) {
244
240
IClass cls = clss .next ();
245
- for (Iterator <? extends IMethod > ms = cls .getDeclaredMethods ().iterator (); ms .hasNext ();) {
241
+ for (Iterator <? extends IMethod > ms = cls .getDeclaredMethods ().iterator (); ms .hasNext (); ) {
246
242
IMethod m = ms .next ();
247
243
if (m .isInit ()) {
248
244
Set <CGNode > nodes = cg .getNodes (m .getReference ());
249
- for (Iterator <CGNode > ns = nodes .iterator (); ns .hasNext ();) {
245
+ for (Iterator <CGNode > ns = nodes .iterator (); ns .hasNext (); ) {
250
246
CGNode n = ns .next ();
251
247
escapeAnalysisRoots .add (heapModel .getPointerKeyForLocal (n , 1 ));
252
248
}
253
249
}
254
250
}
255
251
}
256
252
257
- //
253
+ //
258
254
// compute escaping types: all types flowing to escaping roots and
259
255
// all types transitively reachable through their fields.
260
256
//
@@ -263,10 +259,10 @@ public Set<IClass> gatherThreadEscapingClasses() throws IOException, ClassHierar
263
259
//
264
260
// pass 1: get abstract objects (instance keys) for escaping locations
265
261
//
266
- for (Iterator <PointerKey > rts = escapeAnalysisRoots .iterator (); rts .hasNext ();) {
262
+ for (Iterator <PointerKey > rts = escapeAnalysisRoots .iterator (); rts .hasNext (); ) {
267
263
PointerKey root = rts .next ();
268
264
OrdinalSet <InstanceKey > objects = pa .getPointsToSet (root );
269
- for (Iterator <InstanceKey > objs = objects .iterator (); objs .hasNext ();) {
265
+ for (Iterator <InstanceKey > objs = objects .iterator (); objs .hasNext (); ) {
270
266
InstanceKey obj = objs .next ();
271
267
escapingInstanceKeys .add (obj );
272
268
}
@@ -278,15 +274,15 @@ public Set<IClass> gatherThreadEscapingClasses() throws IOException, ClassHierar
278
274
Set <InstanceKey > newKeys = HashSetFactory .make ();
279
275
do {
280
276
newKeys .clear ();
281
- for (Iterator <InstanceKey > keys = escapingInstanceKeys .iterator (); keys .hasNext ();) {
277
+ for (Iterator <InstanceKey > keys = escapingInstanceKeys .iterator (); keys .hasNext (); ) {
282
278
InstanceKey key = keys .next ();
283
279
IClass type = key .getConcreteType ();
284
280
if (type .isReferenceType ()) {
285
281
if (type .isArrayClass ()) {
286
282
if (((ArrayClass ) type ).getElementClass () != null ) {
287
283
PointerKey fk = heapModel .getPointerKeyForArrayContents (key );
288
284
OrdinalSet <InstanceKey > fobjects = pa .getPointsToSet (fk );
289
- for (Iterator <InstanceKey > fobjs = fobjects .iterator (); fobjs .hasNext ();) {
285
+ for (Iterator <InstanceKey > fobjs = fobjects .iterator (); fobjs .hasNext (); ) {
290
286
InstanceKey fobj = fobjs .next ();
291
287
if (!escapingInstanceKeys .contains (fobj )) {
292
288
newKeys .add (fobj );
@@ -295,12 +291,12 @@ public Set<IClass> gatherThreadEscapingClasses() throws IOException, ClassHierar
295
291
}
296
292
} else {
297
293
Collection <IField > fields = type .getAllInstanceFields ();
298
- for (Iterator <IField > fs = fields .iterator (); fs .hasNext ();) {
294
+ for (Iterator <IField > fs = fields .iterator (); fs .hasNext (); ) {
299
295
IField f = fs .next ();
300
296
if (f .getFieldTypeReference ().isReferenceType ()) {
301
297
PointerKey fk = heapModel .getPointerKeyForInstanceField (key , f );
302
298
OrdinalSet <InstanceKey > fobjects = pa .getPointsToSet (fk );
303
- for (Iterator <InstanceKey > fobjs = fobjects .iterator (); fobjs .hasNext ();) {
299
+ for (Iterator <InstanceKey > fobjs = fobjects .iterator (); fobjs .hasNext (); ) {
304
300
InstanceKey fobj = fobjs .next ();
305
301
if (!escapingInstanceKeys .contains (fobj )) {
306
302
newKeys .add (fobj );
@@ -318,7 +314,7 @@ public Set<IClass> gatherThreadEscapingClasses() throws IOException, ClassHierar
318
314
// get set of types from set of instance keys
319
315
//
320
316
Set <IClass > escapingTypes = HashSetFactory .make ();
321
- for (Iterator <InstanceKey > keys = escapingInstanceKeys .iterator (); keys .hasNext ();) {
317
+ for (Iterator <InstanceKey > keys = escapingInstanceKeys .iterator (); keys .hasNext (); ) {
322
318
InstanceKey key = keys .next ();
323
319
escapingTypes .add (key .getConcreteType ());
324
320
}
@@ -327,27 +323,31 @@ public Set<IClass> gatherThreadEscapingClasses() throws IOException, ClassHierar
327
323
}
328
324
329
325
/**
330
- * This main program shows one example use of thread escape analysis: producing a set of fields to be monitored for a
331
- * dynamic race detector. The idea is that any field might have a race with two exceptions: final fields do not have
332
- * races since there are no writes to them, and volatile fields have atomic read and write semantics provided by the
333
- * VM. Hence, this piece of code produces a list of all other fields.
326
+ * This main program shows one example use of thread escape analysis: producing a set of fields to
327
+ * be monitored for a dynamic race detector. The idea is that any field might have a race with two
328
+ * exceptions: final fields do not have races since there are no writes to them, and volatile
329
+ * fields have atomic read and write semantics provided by the VM. Hence, this piece of code
330
+ * produces a list of all other fields.
331
+ *
334
332
* @throws CancelException
335
333
* @throws IllegalArgumentException
336
334
*/
337
- public static void main (String [] args ) throws IOException , ClassHierarchyException , IllegalArgumentException , CancelException {
335
+ public static void main (String [] args )
336
+ throws IOException , ClassHierarchyException , IllegalArgumentException , CancelException {
338
337
String mainClassName = args [0 ];
339
338
340
339
Set <JarFile > jars = HashSetFactory .make ();
341
340
for (int i = 1 ; i < args .length ; i ++) {
342
341
jars .add (new JarFile (args [i ]));
343
342
}
344
343
345
- Set <IClass > escapingTypes = (new SimpleThreadEscapeAnalysis (jars , mainClassName )).gatherThreadEscapingClasses ();
344
+ Set <IClass > escapingTypes =
345
+ (new SimpleThreadEscapeAnalysis (jars , mainClassName )).gatherThreadEscapingClasses ();
346
346
347
- for (Iterator <IClass > types = escapingTypes .iterator (); types .hasNext ();) {
347
+ for (Iterator <IClass > types = escapingTypes .iterator (); types .hasNext (); ) {
348
348
IClass cls = types .next ();
349
349
if (!cls .isArrayClass ()) {
350
- for (Iterator <IField > fs = cls .getAllFields ().iterator (); fs .hasNext ();) {
350
+ for (Iterator <IField > fs = cls .getAllFields ().iterator (); fs .hasNext (); ) {
351
351
IField f = fs .next ();
352
352
if (!f .isVolatile () && !f .isFinal ()) {
353
353
System .err .println (f .getReference ());
@@ -356,5 +356,4 @@ public static void main(String[] args) throws IOException, ClassHierarchyExcepti
356
356
}
357
357
}
358
358
}
359
-
360
- }
359
+ }
0 commit comments