KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > gov > nasa > jpf > tools > HeapTracker


1 //
2
// Copyright (C) 2005 United States Government as represented by the
3
// Administrator of the National Aeronautics and Space Administration
4
// (NASA). All Rights Reserved.
5
//
6
// This software is distributed under the NASA Open Source Agreement
7
// (NOSA), version 1.3. The NOSA has been approved by the Open Source
8
// Initiative. See the file NOSA-1.3-JPF at the top of the distribution
9
// directory tree for the complete NOSA document.
10
//
11
// THE SUBJECT SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY OF ANY
12
// KIND, EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT
13
// LIMITED TO, ANY WARRANTY THAT THE SUBJECT SOFTWARE WILL CONFORM TO
14
// SPECIFICATIONS, ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR
15
// A PARTICULAR PURPOSE, OR FREEDOM FROM INFRINGEMENT, ANY WARRANTY THAT
16
// THE SUBJECT SOFTWARE WILL BE ERROR FREE, OR ANY WARRANTY THAT
17
// DOCUMENTATION, IF PROVIDED, WILL CONFORM TO THE SUBJECT SOFTWARE.
18
//
19

20 package gov.nasa.jpf.tools;
21
22 import gov.nasa.jpf.PropertyListenerAdapter;
23 import gov.nasa.jpf.VM;
24
25 import gov.nasa.jpf.jvm.ElementInfo;
26 import gov.nasa.jpf.Search;
27 import gov.nasa.jpf.jvm.JVM;
28 import gov.nasa.jpf.jvm.DynamicArea;
29 import gov.nasa.jpf.JPF;
30 import gov.nasa.jpf.Config;
31 import gov.nasa.jpf.jvm.ThreadInfo;
32 import gov.nasa.jpf.util.DynamicObjectArray;
33 import gov.nasa.jpf.jvm.MethodInfo;
34 import gov.nasa.jpf.util.SourceRef;
35 import gov.nasa.jpf.jvm.ClassInfo;
36
37 import java.util.Stack JavaDoc;
38 import java.util.Iterator JavaDoc;
39 import java.util.regex.Pattern JavaDoc;
40
41 /**
42  * HeapTracker - property-listener class to check heap utilization along all
43  * execution paths (e.g. to verify heap bounds)
44  */

45 public class HeapTracker extends PropertyListenerAdapter {
46   
47   class PathStat implements Cloneable JavaDoc {
48     int nNew = 0;
49     int nReleased = 0;
50     int heapSize = 0; // in bytes
51

52     public Object JavaDoc clone() {
53       try {
54         return super.clone();
55       } catch (CloneNotSupportedException JavaDoc e) {
56         return null;
57       }
58     }
59   }
60       
61   PathStat stat = new PathStat();
62   Stack JavaDoc pathStats = new Stack JavaDoc();
63   
64   DynamicObjectArray loc = new DynamicObjectArray();
65   
66   int maxState;
67   int nForward;
68   int nBacktrack;
69   
70   int nElemTotal;
71   int nGcTotal;
72   int nSharedTotal;
73   int nImmutableTotal;
74   
75   int nElemMax = Integer.MIN_VALUE;
76   int nElemMin = Integer.MAX_VALUE;
77   int nElemAv;
78   
79   int pElemSharedMax = Integer.MIN_VALUE;
80   int pElemSharedMin = Integer.MAX_VALUE;
81   int pElemSharedAv;
82   
83   int pElemImmutableMax = Integer.MIN_VALUE;
84   int pElemImmutableMin = Integer.MAX_VALUE;
85   int pElemImmutableAv;
86   
87   int nReleased;
88   int nReleasedTotal;
89   int nReleasedAv;
90   int nReleasedMax = Integer.MIN_VALUE;
91   int nReleasedMin = Integer.MAX_VALUE;
92   
93   int maxPathHeap = Integer.MIN_VALUE;
94   int maxPathNew = Integer.MIN_VALUE;
95   int maxPathReleased = Integer.MIN_VALUE;
96   int maxPathAlive = Integer.MIN_VALUE;
97
98   int initHeap = 0;
99   int initNew = 0;
100   int initReleased = 0;
101   int initAlive = 0;
102
103   // used as a property check
104
int maxHeapSizeLimit;
105   int maxLiveLimit;
106   boolean throwOutOfMemory = false;
107   Pattern JavaDoc classPattern = null;
108   
109   void updateMaxPathValues() {
110       if (stat.heapSize > maxPathHeap) {
111         maxPathHeap = stat.heapSize;
112       }
113       
114       if (stat.nNew > maxPathNew) {
115         maxPathNew = stat.nNew;
116       }
117       
118       if (stat.nReleased > maxPathReleased) {
119         maxPathReleased = stat.nReleased;
120       }
121       
122       int nAlive = stat.nNew - stat.nReleased;
123       if (nAlive > maxPathAlive) {
124         maxPathAlive = nAlive;
125       }
126   }
127
128   public HeapTracker (Config config) {
129     maxHeapSizeLimit = config.getInt("heap.size_limit", -1);
130     maxLiveLimit = config.getInt("heap.live_limit", -1);
131     throwOutOfMemory = config.getBoolean("heap.throw_exception");
132     
133     String JavaDoc regEx = config.getString("heap.classes");
134     if (regEx != null) {
135       classPattern = Pattern.compile(regEx);
136     }
137   }
138   
139   /******************************************* abstract Property *****/
140
141   /**
142    * return 'false' if property is violated
143    */

144   public boolean check (VM vm, Object JavaDoc arg) {
145     if (throwOutOfMemory) {
146       // in this case we don't want to stop the program, but see if it
147
// behaves gracefully - don't report a property violation
148
return true;
149     } else {
150       if ((maxHeapSizeLimit >= 0) && (stat.heapSize > maxHeapSizeLimit)) {
151         return false;
152       }
153       if ((maxLiveLimit >=0) && ((stat.nNew - stat.nReleased) > maxLiveLimit)) {
154         return false;
155       }
156       
157       return true;
158     }
159   }
160
161   public String JavaDoc getErrorMessage () {
162     return "heap limit exceeded: " + stat.heapSize + " > " + maxHeapSizeLimit;
163   }
164   
165   /******************************************* SearchListener interface *****/
166   public void searchStarted(Search search) {
167     super.searchStarted(search);
168     
169     updateMaxPathValues();
170     pathStats.push(stat);
171     
172     initHeap = stat.heapSize;
173     initNew = stat.nNew;
174     initReleased = stat.nReleased;
175     initAlive = initNew - initReleased;
176     
177     stat = (PathStat)stat.clone();
178   }
179   
180   public void stateAdvanced(Search search) {
181     
182     if (search.isNewState()) {
183       int id = search.getStateNumber();
184
185       if (id > maxState) maxState = id;
186       
187       updateMaxPathValues();
188       pathStats.push(stat);
189       stat = (PathStat)stat.clone();
190       
191       nForward++;
192     }
193   }
194   
195   public void stateBacktracked(Search search) {
196     nBacktrack++;
197     
198     if (!pathStats.isEmpty()){
199       stat = (PathStat) pathStats.pop();
200     }
201   }
202   
203   public void searchFinished(Search search) {
204     System.out.println("heap statistics:");
205     System.out.println(" states: " + maxState);
206     System.out.println(" forwards: " + nForward);
207     System.out.println(" backtrack: " + nBacktrack);
208     System.out.println();
209     System.out.println(" gc cycles: " + nGcTotal);
210     System.out.println();
211     System.out.println(" max Objects: " + nElemMax);
212     System.out.println(" min Objects: " + nElemMin);
213     System.out.println(" avg Objects: " + nElemAv);
214     System.out.println();
215     System.out.println(" max% shared: " + pElemSharedMax);
216     System.out.println(" min% shared: " + pElemSharedMin);
217     System.out.println(" avg% shared: " + pElemSharedAv);
218     System.out.println();
219     System.out.println(" max% immutable: " + pElemImmutableMax);
220     System.out.println(" min% immutable: " + pElemImmutableMin);
221     System.out.println(" avg% immutable: " + pElemImmutableAv);
222     System.out.println();
223     System.out.println(" max released: " + nReleasedMax);
224     System.out.println(" min released: " + nReleasedMin);
225     System.out.println(" avg released: " + nReleasedAv);
226     
227     System.out.println();
228     System.out.print( " max path heap (B): " + maxPathHeap);
229     System.out.println(" / " + (maxPathHeap - initHeap));
230     System.out.print( " max path alive: " + maxPathAlive);
231     System.out.println(" / " + (maxPathAlive - initAlive));
232     System.out.print( " max path new: " + maxPathNew);
233     System.out.println(" / " + (maxPathNew - initNew));
234     System.out.print( " max path released: " + maxPathReleased);
235     System.out.println(" / " + (maxPathReleased - initReleased));
236   }
237   
238   
239   /******************************************* VMListener interface *********/
240   public void gcBegin(VM vm) {
241     JVM jvm = (JVM)vm;
242     /**
243      System.out.println();
244      System.out.println( "----- gc cycle: " + jvm.getDynamicArea().getGcNumber()
245      + ", state: " + jvm.getStateId());
246      **/

247   }
248   
249   public void gcEnd(VM vm) {
250     JVM jvm = (JVM)vm;
251     DynamicArea da = jvm.getDynamicArea();
252     Iterator JavaDoc it = da.iterator();
253     
254     int n = 0;
255     int nShared = 0;
256     int nImmutable = 0;
257     
258     while (it.hasNext()) {
259       ElementInfo ei = (ElementInfo) it.next();
260       n++;
261       
262       if (ei.isShared()) nShared++;
263       if (ei.isImmutable()) nImmutable++;
264       
265       //printElementInfo(ei);
266
}
267     
268     nElemTotal += n;
269     nGcTotal++;
270     
271     if (n > nElemMax) nElemMax = n;
272     if (n < nElemMin) nElemMin = n;
273     
274     int pShared = (nShared * 100) / n;
275     int pImmutable = (nImmutable * 100) / n;
276     
277     if (pShared > pElemSharedMax) pElemSharedMax = pShared;
278     if (pShared < pElemSharedMin) pElemSharedMin = pShared;
279     
280     nSharedTotal += nShared;
281     nImmutableTotal += nImmutable;
282     
283     pElemSharedAv = (nSharedTotal * 100) / nElemTotal;
284     pElemImmutableAv = (nImmutableTotal * 100) / nElemTotal;
285     
286     if (pImmutable > pElemImmutableMax) pElemImmutableMax = pImmutable;
287     if (pImmutable < pElemImmutableMin) pElemImmutableMin = pImmutable;
288     
289     nElemAv = nElemTotal / nGcTotal;
290     nReleasedAv = nReleasedTotal / nGcTotal;
291     
292     if (nReleased > nReleasedMax) nReleasedMax = nReleased;
293     if (nReleased < nReleasedMin) nReleasedMin = nReleased;
294     
295     nReleased = 0;
296   }
297
298   boolean isRelevantType (ElementInfo ei) {
299     if (classPattern == null) return true;
300     
301     return classPattern.matcher(ei.getClassInfo().getName()).matches();
302   }
303   
304   public void objectCreated(VM vm) {
305     JVM jvm = (JVM)vm;
306     ElementInfo ei = jvm.getLastElementInfo();
307     int idx = ei.getIndex();
308     ThreadInfo ti = jvm.getLastThreadInfo();
309     int line = ti.getLine();
310     MethodInfo mi = ti.getMethod();
311     SourceRef sr = null;
312     
313     if (!isRelevantType(ei)) {
314       return;
315     }
316     
317     if (mi != null) {
318       String JavaDoc file = mi.getClassInfo().getSourceFileName();
319       
320       if (file != null) {
321         sr = new SourceRef(file, line);
322       } else {
323         ClassInfo ci = ti.getMethod().getClassInfo();
324         sr = new SourceRef(ci.getName(), line);
325       }
326     }
327     
328     loc.set(idx, sr);
329     
330     stat.nNew++;
331     stat.heapSize += ei.getHeapSize();
332     
333     // check if we should simulate an OutOfMemoryError
334
if (throwOutOfMemory) {
335       if (((maxHeapSizeLimit >=0) && (stat.heapSize > maxHeapSizeLimit)) ||
336           ((maxLiveLimit >=0) && ((stat.nNew - stat.nReleased) > maxLiveLimit))){
337         DynamicArea.getHeap().setOutOfMemory(true);
338       }
339     }
340   }
341   
342   public void objectReleased(VM vm) {
343     JVM jvm = (JVM)vm;
344     ElementInfo ei = jvm.getLastElementInfo();
345     
346     if (!isRelevantType(ei)) {
347       return;
348     }
349     
350     nReleasedTotal++;
351     nReleased++;
352     
353     stat.nReleased++;
354     stat.heapSize -= ei.getHeapSize();
355   }
356   
357   /****************************************** private stuff ******/
358   private void printElementInfo(ElementInfo ei) {
359     boolean first = false;;
360     
361     System.out.print( ei.getIndex());
362     System.out.print( ": ");
363     System.out.print( ei.getClassInfo().getName());
364     System.out.print( " [");
365     
366     if (ei.isShared()) {
367       System.out.print( "shared");
368       first = false;
369     }
370     if (ei.isImmutable()) {
371       if (!first) System.out.print(' ');
372       System.out.print( "immutable");
373     }
374     System.out.print( "] ");
375     
376     SourceRef sr = (SourceRef)loc.get(ei.getIndex());
377     if (sr != null) {
378       System.out.println(sr);
379     } else {
380       System.out.println("?");
381     }
382   }
383   
384   
385   static void printUsage () {
386     System.out.println("HeapTracker - a JPF listener tool to report and check heap utilization");
387     System.out.println("usage: java gov.nasa.jpf.tools.HeapTracker <jpf-options> <heapTracker-options> <class>");
388     System.out.println(" +heap.size_limit=<num> : report property violation if heap exceeds <num> bytes");
389     System.out.println(" +heap.live_limit=<num> : report property violation if more than <num> live objects");
390     System.out.println(" +heap.classes=<regEx> : only report instances of classes matching <regEx>");
391     System.out.println(" +heap.throw_exception=<bool>: throw a OutOfMemoryError instead of reporting property violation");
392   }
393
394   
395   public static void main (String JavaDoc[] args) {
396     if (args.length == 0) {
397       printUsage();
398       return;
399     }
400     Config conf = JPF.createConfig(args);
401     // set own options here..
402

403     HeapTracker listener = new HeapTracker(conf);
404     
405     JPF jpf = new JPF(conf);
406     jpf.addSearchListener(listener);
407     jpf.addVMListener(listener);
408
409     if (listener.maxHeapSizeLimit >= 0) {
410       jpf.addSearchProperty(listener);
411     }
412     
413     jpf.run();
414   }
415 }
416
417
Popular Tags