1 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 ; 38 import java.util.Iterator ; 39 import java.util.regex.Pattern ; 40 41 45 public class HeapTracker extends PropertyListenerAdapter { 46 47 class PathStat implements Cloneable { 48 int nNew = 0; 49 int nReleased = 0; 50 int heapSize = 0; 52 public Object clone() { 53 try { 54 return super.clone(); 55 } catch (CloneNotSupportedException e) { 56 return null; 57 } 58 } 59 } 60 61 PathStat stat = new PathStat(); 62 Stack pathStats = new Stack (); 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 int maxHeapSizeLimit; 105 int maxLiveLimit; 106 boolean throwOutOfMemory = false; 107 Pattern 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 regEx = config.getString("heap.classes"); 134 if (regEx != null) { 135 classPattern = Pattern.compile(regEx); 136 } 137 } 138 139 140 141 144 public boolean check (VM vm, Object arg) { 145 if (throwOutOfMemory) { 146 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 getErrorMessage () { 162 return "heap limit exceeded: " + stat.heapSize + " > " + maxHeapSizeLimit; 163 } 164 165 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 240 public void gcBegin(VM vm) { 241 JVM jvm = (JVM)vm; 242 247 } 248 249 public void gcEnd(VM vm) { 250 JVM jvm = (JVM)vm; 251 DynamicArea da = jvm.getDynamicArea(); 252 Iterator 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 } 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 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 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 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 [] args) { 396 if (args.length == 0) { 397 printUsage(); 398 return; 399 } 400 Config conf = JPF.createConfig(args); 401 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 |