1
2
3
4
5
6
7
8
9
10
11
12
13
14 package net.sf.madmap;
15
16 import java.util.*;
17 import java.util.concurrent.*;
18 import java.io.*;
19
20 import javax.swing.JProgressBar;
21 import javax.swing.JOptionPane;
22 import java.lang.management.*;
23 import javax.management.*;
24
25
26
27
28
29
30
31
32
33 public class Madmap implements MadmapMBean, Runnable {
34 static File _hprofFile = null;
35 String _fileName;
36 boolean _isBinary = false;
37 long _startTime = 0;
38 ILogger _logger = (ILogger)(MadmapMain.appContext()).getBean("logger");
39 IResources _resources = (IResources)(MadmapMain.appContext()).getBean("resources");
40 IHprofReader _reader = (IHprofReader)(MadmapMain.appContext()).getBean("reader");
41 IHprofReader _binReader = (IHprofReader)(MadmapMain.appContext()).getBean("binReader");
42
43 ConcurrentHashMap<HprofHeapAllocation,HprofHeapAllocation> _heap_objects_table = new ConcurrentHashMap<HprofHeapAllocation,HprofHeapAllocation>();
44 ConcurrentHashMap<HprofClassElement,HprofClassElement> _class_list = new ConcurrentHashMap<HprofClassElement,HprofClassElement>();
45
46 ConcurrentHashMap _leak_guess_table = null;
47 ConcurrentHashMap _stack_trace_table = new ConcurrentHashMap();
48 ConcurrentHashMap _threads_list = new ConcurrentHashMap();
49 Vector _roots_list = new Vector( 1024 );
50 ConcurrentHashMap _finalizable_class_list = new ConcurrentHashMap();
51
52 MainWindow _window;
53
54
55 public String getMsg() { return "Thanks for using the Madmap MBean."; }
56
57 public boolean getVerbose() { return MadmapMain.verbose(); }
58 public void setVerbose(boolean x) { MadmapMain.setVerbose(x); }
59
60 public String getFilename() { return _fileName; }
61 public boolean isBinary() { return _isBinary; }
62
63
64
65
66 HprofClassElement boolArrayKlass = null;
67 HprofClassElement byteArrayKlass = null;
68 HprofClassElement charArrayKlass = null;
69 HprofClassElement shortArrayKlass = null;
70 HprofClassElement intArrayKlass = null;
71 HprofClassElement longArrayKlass = null;
72 HprofClassElement floatArrayKlass = null;
73 HprofClassElement doubleArrayKlass = null;
74
75
76
77
78
79 static final int fakeBoolArrayKlassAddr = -1;
80 static final int fakeByteArrayKlassAddr = -2;
81 static final int fakeCharArrayKlassAddr = -3;
82 static final int fakeShortArrayKlassAddr = -4;
83 static final int fakeIntArrayKlassAddr = -5;
84 static final int fakeLongArrayKlassAddr = -6;
85 static final int fakeFloatArrayKlassAddr = -7;
86 static final int fakeDoubleArrayKlassAddr = -8;
87
88 static final HprofClassElement fakeBoolArrayKlass = new HprofClassElement(fakeBoolArrayKlassAddr, "bool_fake_array_class");
89 static final HprofClassElement fakeByteArrayKlass = new HprofClassElement(fakeByteArrayKlassAddr, "byte_fake_array_class");
90 static final HprofClassElement fakeCharArrayKlass = new HprofClassElement(fakeCharArrayKlassAddr, "char_fake_array_class");
91 static final HprofClassElement fakeShortArrayKlass = new HprofClassElement(fakeShortArrayKlassAddr, "short_fake_array_class");
92 static final HprofClassElement fakeIntArrayKlass = new HprofClassElement(fakeIntArrayKlassAddr, "int_fake_array_class");
93 static final HprofClassElement fakeLongArrayKlass = new HprofClassElement(fakeLongArrayKlassAddr, "long_fake_array_class");
94 static final HprofClassElement fakeFloatArrayKlass = new HprofClassElement(fakeFloatArrayKlassAddr, "float_fake_array_class");
95 static final HprofClassElement fakeDoubleArrayKlass = new HprofClassElement(fakeDoubleArrayKlassAddr, "double_fake_array_class");
96
97 public static HprofClassElement getFakeArrayClass( String nm ) {
98 HprofClassElement cls_addr = null;
99 if ((nm == "boolean[]") || (nm == "boolean") || (nm == "[Z")) {
100 cls_addr = fakeBoolArrayKlass;
101 } else if ((nm == "byte[]") || (nm == "byte") || (nm == "[B")) {
102 cls_addr = fakeByteArrayKlass;
103 } else if ((nm == "char[]") || (nm == "char") || (nm == "[C")) {
104 cls_addr = fakeCharArrayKlass;
105 } else if (( nm == "short[]") || (nm == "short") || (nm == "[S")) {
106 cls_addr = fakeShortArrayKlass;
107 } else if ((nm == "int[]") || (nm == "int") || (nm == "[I")) {
108 cls_addr = fakeIntArrayKlass;
109 } else if ((nm == "long[]") || (nm == "long") || (nm == "[J")) {
110 cls_addr = fakeLongArrayKlass;
111 } else if ((nm == "float[]") || (nm == "float") || (nm == "[F")) {
112 cls_addr = fakeFloatArrayKlass;
113 } else if ((nm == "double[]") || (nm == "double") || (nm == "[D")) {
114 cls_addr = fakeDoubleArrayKlass;
115 } else {
116 System.out.println( "### No match for basic type array: " + nm );
117 assert true == false : "should not reach here!";
118 }
119
120 return cls_addr;
121 }
122
123
124 public static void setFile( File f ) {
125 _hprofFile = f;
126 }
127
128 public ConcurrentHashMap<HprofHeapAllocation,HprofHeapAllocation> getObjects() { return _heap_objects_table; }
129 public ConcurrentHashMap getGuesses() { return _leak_guess_table; }
130
131 public ConcurrentHashMap getStackTraces() { return _stack_trace_table; }
132 public ConcurrentHashMap getThreads() { return _threads_list; }
133 public Vector getRoots() { return _roots_list; }
134 public ConcurrentHashMap<HprofClassElement,HprofClassElement> getClasses() { return _class_list; }
135
136 public float elapsedTime() {
137 return (float)(System.currentTimeMillis() - _startTime)/(float)1000.0;
138 }
139
140 public void run() {
141 _logger.myLog( getWindow(), " " );
142 _logger.myLog( getWindow(), "=================================================================================" );
143 _logger.myLog( getWindow(), "Execution environment for this run: " );
144 _logger.myLog( getWindow(), "madmap version\t= " + _resources.getString("version") );
145 _logger.myLog( getWindow(), "java version\t= " + System.getProperty ( "java.version" ) );
146 _logger.myLog( getWindow(), "os name\t= " + System. getProperty ( "os.name" ) );
147 _logger.myLog( getWindow(), "os version\t= " + System. getProperty ( "os.version" ) );
148 _logger.myLog( getWindow(), "default locale\t= " + java.util.Locale.getDefault() );
149 _logger.myLog( getWindow(), "cwd\t= " + System.getProperty("user.dir") );
150 _logger.myLog( getWindow(), "Total memory\t= " + Runtime.getRuntime().totalMemory() );
151 _logger.myLog( getWindow(), "Max memory\t= " + Runtime.getRuntime().maxMemory() );
152 _logger.myLog( getWindow(), "Free memory\t= " + Runtime.getRuntime().freeMemory() );
153 _logger.myLog( getWindow(), "Processors\t= " + Runtime.getRuntime().availableProcessors() );
154 _logger.myLog( getWindow(), "=================================================================================" );
155 _logger.myLog( getWindow(), " " );
156 init();
157 }
158
159 public void init()
160 {
161 _startTime = System.currentTimeMillis();
162 if (isBinary()) {
163 _binReader.parse( this, _fileName );
164 } else{
165 _reader.parse( this, _fileName );
166 }
167 if ( MadmapMain.runDump() ) {
168 dumpCollectedInfo( true, true, true, true, false);
169 }
170 analyze();
171 }
172
173 public void dumpCollectedInfo( boolean thds, boolean stacks, boolean roots, boolean classes, boolean objects ) {
174 _logger.myLog( getWindow(), "==================================================================================================== " );
175 _logger.myLog( getWindow(), "Dumping tables... " );
176
177 if ( thds == true ) {
178
179 _logger.myLog( getWindow(), "Dumping Threads... " );
180 Collection<HprofThreadData> htc = this.getThreads().values();
181 Iterator<HprofThreadData> ihtc = htc.iterator();
182 while( ihtc.hasNext() ) {
183 HprofThreadData ho = ihtc.next();
184 _logger.myLog( getWindow(), ho.toString() );
185 }
186 _logger.myLog( getWindow(), "==================================================================================================== " );
187 }
188
189 if ( stacks == true ) {
190
191 _logger.myLog( getWindow(), "Dumping Stack traces... " );
192 Collection<HprofStackTraceData> htc = this.getStackTraces().values();
193 Iterator<HprofStackTraceData> ihtc = htc.iterator();
194 while( ihtc.hasNext() ) {
195 HprofStackTraceData sd = ihtc.next();
196 _logger.myLog( getWindow(), sd.toString() );
197
198 }
199 _logger.myLog( getWindow(), "==================================================================================================== " );
200 }
201
202 if ( roots == true ) {
203
204 _logger.myLog( getWindow(), "Dumping Roots... " );
205 for( int i = 0; i < this.getRoots().size(); i++ ) {
206 HprofRoot rt = (HprofRoot) this.getRoots().get(i);
207 _logger.myLog( getWindow(), rt.toString() );
208
209 }
210 _logger.myLog( getWindow(), "==================================================================================================== " );
211 }
212
213 if ( classes == true ) {
214
215 _logger.myLog( getWindow(), "Dumping Classes... " );
216 Collection<HprofClassElement> cc = this.getClasses().values();
217 Iterator<HprofClassElement> icc = cc.iterator();
218 while( icc.hasNext() ) {
219 HprofClassElement ho = icc.next();
220 _logger.myLog( getWindow(), ho.toString() );
221 }
222 _logger.myLog( getWindow(), "==================================================================================================== " );
223 }
224
225 try {
226
227 if ( objects == true ) {
228
229 _logger.myLog( getWindow(), "Dumping Objects... " );
230 Collection<HprofHeapAllocation> hoc = this.getObjects().values();
231 Iterator<HprofHeapAllocation> ihoc = hoc.iterator();
232
233 while( ihoc.hasNext() ) {
234 HprofHeapAllocation ho = ihoc.next();
235 assert ho != null : "ho was null!";
236 _logger.myLog( getWindow(), ho.toString() );
237 }
238 _logger.myLog( getWindow(), "==================================================================================================== " );
239 }
240
241 } catch (Exception e) {
242 e.printStackTrace();
243 }
244 }
245
246
247 long _live_objects = 0;
248 long _liveObjectsSize = 0;
249 long _totalObjectsSize = 0;
250 long _total_finalizers = 0;
251
252 public void printFinalizers() {
253 Collection<HprofHeapAllocation> hoc = this.getObjects().values();
254 Iterator<HprofHeapAllocation> ihoc = hoc.iterator();
255 HprofHeapCollectable ho = null;
256
257 _logger.myLog( getWindow(), "==================================================================================================== " );
258
259 while( ihoc.hasNext() ) {
260 ho = (HprofHeapCollectable)ihoc.next();
261 if ( ho instanceof HprofClassElement ) {
262 continue;
263 }
264
265 if ( (((HprofHeapAllocation)ho).className()).equals("java.lang.ref.Finalizer") ||
266 (((HprofHeapAllocation)ho).className()).equals("java/lang/ref/Finalizer")) {
267 long referent;
268 HprofHeapAllocation horef = null;
269
270 _total_finalizers++;
271
272
273 referent = (ho.children())[ 2 ];
274 horef = ( HprofObject ) _heap_objects_table.get( new HprofHeapElement(referent) );
275 if ( ( horef.className().equals("java.lang.ref.Finalizer")) ) {
276
277 referent = (ho.children())[ 0 ];
278 horef = (HprofObject) _heap_objects_table.get( new HprofHeapElement(referent) );
279 }
280
281 assert referent != 0 : "finalizer referent is null!" ;
282 assert horef != null : "finalizer referent not found in heap!" ;
283 if ( MadmapMain.runDump() ) {
284 System.out.println( "## Finalizer referent: " + referent + " = " + horef.toString());
285 }
286
287
288 HprofClassElement currClass = horef.getActualClass();
289 HprofClassElement c2 = (HprofClassElement)_finalizable_class_list.get((int)currClass.addr());
290 if (c2 == null) {
291 _finalizable_class_list.put( (int)currClass.addr(), currClass );
292 } else {
293 assert c2 == currClass : "referent classes should match?";
294 }
295
296 currClass.setFinalizableCount( currClass.getFinalizableCount() + 1 );
297 currClass.setFinalizableSize( currClass.getFinalizableSize() + horef.size() );
298 }
299 }
300
301 java.util.ArrayList<HprofClassElement> fList = new java.util.ArrayList<HprofClassElement>();
302
303 fList.addAll(_finalizable_class_list.values());
304 Collections.sort(fList, new FinalizeComparator());
305
306 if ( ! MadmapMain.noGUI() ) {
307 getWindow().addFinalizerHeapTab( fList );
308 }
309
310 _logger.myLog( getWindow(), "Summary of finalizable objects sorted by cumulative size: " );
311 _logger.myLog( getWindow(), " " );
312 _logger.myLog( getWindow(), "Size\t\tCount\t\tClass" );
313 _logger.myLog( getWindow(), "==================================================================================================== " );
314
315 Iterator<HprofClassElement> ihoc3 = fList.iterator();
316 while( ihoc3.hasNext() ) {
317 HprofClassElement hk = ihoc3.next();
318 int ic = hk.getFinalizableCount();
319 long is = hk.getFinalizableSize();
320
321 if ( ic > 0 ) {
322 _logger.myLog( getWindow(), is + "\t\t" + ic + "\t\t" + hk.className() + "@" + Long.toHexString( hk.addr() ) );
323 }
324 }
325 _logger.myLog( getWindow(), "==================================================================================================== " );
326 _logger.myLog( getWindow(), " " );
327 _logger.myLog( getWindow(), elapsedTime() + ": Total count of finalizers: " + _total_finalizers );
328 }
329
330
331 public void buildLiveObjectsTable() {
332 long totalSize = this.getObjects().size();
333 long size = 0;
334 long lowestHeapAddr = (long) Long.MAX_VALUE;
335 long highestHeapAddr = 0;
336 HprofHeapAllocation biggestObj = null;
337 long biggestObjSize = 0;
338 HprofHeapAllocation biggestArr = null;
339 long biggestArrSize = 0;
340 long deadObjects = 0;
341 int progressCounter = 0;
342 JProgressBar progress_bar = null;
343
344 if ( ! MadmapMain.noGUI() ) {
345 progress_bar = getWindow().getProgressBar();
346 getWindow().getLabelForProgressBar().setText("Removing Dead Objects");
347
348 progress_bar.setMinimum(0);
349 progress_bar.setMaximum(this.getObjects().size() - 1);
350 progress_bar.setValue(0);
351
352 getWindow().updateMemoryProgressBar();
353 }
354
355 for (Enumeration e = this.getObjects().keys() ; e.hasMoreElements() ; ) {
356 Object theKey = e.nextElement();
357 HprofHeapAllocation ho = (HprofHeapAllocation) this.getObjects().get( theKey );
358 size = ho.size();
359 long currObjAddr = ho.addr();
360
361 if ( currObjAddr == 0 ) {
362 System.out.println( "Found 0 addr object?! = " + ho );
363 _logger.myLog( getWindow(), ho.toString() );
364 }
365
366
367 if ( currObjAddr < lowestHeapAddr ) {
368 assert currObjAddr != 0 : "object addr is messed up." ;
369 lowestHeapAddr = currObjAddr;
370 }
371 if ( currObjAddr > highestHeapAddr ) {
372 highestHeapAddr = currObjAddr;
373 }
374
375 _totalObjectsSize += size;
376 if ( ho.isAlive() ) {
377
378
379
380
381
382 HprofClassElement klass_addr = ho.class_addr();
383
384 if ( klass_addr == fakeBoolArrayKlass ) {
385 ho.set_class_addr( boolArrayKlass );
386 assert ho instanceof HprofArrayObject : "Class is wrong for array type";
387 } else if ( klass_addr == fakeByteArrayKlass ) {
388 ho.set_class_addr( byteArrayKlass );
389 assert ho instanceof HprofArrayObject : "Class is wrong for array type";
390 } else if ( klass_addr == fakeCharArrayKlass ) {
391 ho.set_class_addr( charArrayKlass );
392 assert ho instanceof HprofArrayObject : "Class is wrong for array type";
393 } else if ( klass_addr == fakeShortArrayKlass ) {
394 ho.set_class_addr( shortArrayKlass );
395 assert ho instanceof HprofArrayObject : "Class is wrong for array type";
396 } else if ( klass_addr == fakeIntArrayKlass ) {
397 ho.set_class_addr( intArrayKlass );
398 assert ho instanceof HprofArrayObject : "Class is wrong for array type";
399 } else if ( klass_addr == fakeLongArrayKlass ) {
400 ho.set_class_addr( longArrayKlass );
401 assert ho instanceof HprofArrayObject : "Class is wrong for array type";
402 } else if ( klass_addr == fakeFloatArrayKlass ) {
403 ho.set_class_addr( floatArrayKlass );
404 assert ho instanceof HprofArrayObject : "Class is wrong for array type";
405 } else if ( klass_addr == fakeDoubleArrayKlass ) {
406 ho.set_class_addr( doubleArrayKlass );
407 assert ho instanceof HprofArrayObject : "Class is wrong for array type";
408 }
409
410 _live_objects++;
411 _liveObjectsSize += size;
412
413
414 if ( ho instanceof HprofArrayObject ) {
415 if ( size > biggestArrSize ) {
416 biggestArr = (HprofHeapAllocation) ho;
417 biggestArrSize = size;
418 }
419 } else if ( (ho instanceof HprofObject)
420 if ( size > biggestObjSize ) {
421 biggestObj = (HprofHeapAllocation) ho;
422 biggestObjSize = size;
423 }
424 } else {
425 _logger.myLog( getWindow(), "Unknown instance: " );
426 _logger.myLog( getWindow(), ho.toString() );
427 }
428 } else {
429
430 if ( MadmapMain.runDump() ) {
431 System.out.println( "Removed: " + ho.className() + "@" + Long.toHexString( ho.addr() ) );
432 }
433
434 this.getObjects().remove( theKey );
435 deadObjects++;
436 }
437
438 if( ( ! MadmapMain.noGUI() ) && ((progressCounter++) % 100 == 0)) {
439 progress_bar.setValue(progressCounter);
440 getWindow().updateMemoryProgressBar();
441 }
442 }
443
444 if ( ! MadmapMain.noGUI() ) {
445 progress_bar.setValue(progress_bar.getMaximum());
446 getWindow().updateMemoryProgressBar();
447 }
448
449 _logger.myLog( getWindow(), "\n");
450 _logger.myLog( getWindow(), "Objects in Heap:" );
451 _logger.myLog( getWindow(), " Total : " + totalSize );
452 _logger.myLog( getWindow(), " Total size : " + _totalObjectsSize );
453 _logger.myLog( getWindow(), " Live : " + _live_objects );
454 _logger.myLog( getWindow(), " Live size : " + _liveObjectsSize );
455 _logger.myLog( getWindow(), " Unreferenced: " + ( totalSize - _live_objects ));
456 _logger.myLog( getWindow(), " Removed : " + deadObjects );
457 _logger.myLog( getWindow(), " Lowest object start address : " + Long.toHexString(lowestHeapAddr) );
458 _logger.myLog( getWindow(), " Highest object start address: " + Long.toHexString(highestHeapAddr) );
459 _logger.myLog( getWindow(), " Size of heap range : 0x" + Long.toHexString(highestHeapAddr - lowestHeapAddr) + " == " + (highestHeapAddr - lowestHeapAddr));
460
461 if ( biggestObj != null ) {
462 _logger.myLog( getWindow(), "Biggest Array:" );
463
464 _logger.myLog( getWindow(), new String(Long.toHexString(biggestArr.addr()) + " " + biggestArr.className() + " size=" + biggestArr.size()));
465
466 if ( false ) {
467 _logger.myLog( getWindow(), biggestArr.toString() );
468 _logger.myLog( getWindow(), "\n");
469 }
470 _logger.myLog( getWindow(), "Biggest Object:" );
471 _logger.myLog( getWindow(), biggestObj.toString() );
472 }
473 }
474
475
476 int _totalMarkedLive = 0;
477 java.util.Stack<HprofHeapElement> _marking_stack = new java.util.Stack<HprofHeapElement>();
478
479
480
481 public void markChildren( HprofHeapCollectable ho ) {
482 int markedInThisPass = 0;
483
484 assert _marking_stack.empty() : "starting markChildren but _marking_stack is not empty! " ;
485
486 if ( ! ho.isAlive() ) {
487 ho.setLiveness( true );
488 _totalMarkedLive++;
489 markedInThisPass++;
490
491
492
493
494
495
496 long numChildren = ho.children_size();
497 for ( int i = 0; i < numChildren; i++ ) {
498 _marking_stack.push( new HprofHeapElement( (long)ho.children()[i] ));
499 }
500
501
502 while ( ! _marking_stack.empty() ) {
503
504
505 HprofHeapElement addr = (HprofHeapElement)_marking_stack.pop();
506
507
508 HprofHeapCollectable child = (HprofHeapCollectable) this.getObjects().get( addr );
509
510
511 if ( child == null ) {
512
513
514
515 child = (HprofHeapCollectable) this.getClasses().get( addr );
516 }
517
518 if ( child == null ) {
519
520
521
522
523 } else {
524
525 if ( ! child.isAlive() ) {
526 child.setLiveness( true );
527 _totalMarkedLive++;
528 markedInThisPass++;
529
530
531 numChildren = child.children_size();
532 for ( int i = 0; i < numChildren; i++ ) {
533 _marking_stack.push( new HprofHeapElement(child.children()[i]) );
534 }
535 }
536 }
537 }
538 } else {
539
540
541
542
543
544 }
545
546
547
548
549 assert _marking_stack.empty() : "exiting markChildren but _marking_stack is not empty! " ;
550 }
551
552
553 private void iterativeMarking() {
554 JProgressBar progress_bar = null;
555
556 try {
557
558 _logger.myLog( getWindow(), elapsedTime() + ": analyze: iterative marking" );
559
560 if ( ! MadmapMain.noGUI() ) {
561 progress_bar = getWindow().getProgressBar();
562 getWindow().getLabelForProgressBar().setText("Marking Live Objects");
563 progress_bar.setMinimum(0);
564 progress_bar.setMaximum(this.getRoots().size() - 1);
565 progress_bar.setValue(0);
566 }
567
568
569 {
570 for ( int i = 0; i < this.getRoots().size(); i++ ) {
571 HprofHeapCollectable ho;
572
573
574 ho = (HprofHeapCollectable) this.getClasses().get( new HprofHeapElement(((HprofRoot)this.getRoots().get(i)).addr()) );
575
576
577 if ( ho == null ) {
578 ho = (HprofHeapCollectable) this.getObjects().get( new HprofHeapElement( ((HprofRoot)this.getRoots().get(i)).addr() ));
579 }
580
581 if ( ho != null ) {
582 markChildren( ho );
583 } else {
584
585 if (i != 0 && MadmapMain.verbose() && (((HprofRoot)this.getRoots().get(i)).rootType().equals("<system class>"))) {
586 _logger.myLog( getWindow(), "# Cannot find system class root[" + i + "]: " + this.getRoots().get(i) + " in heap table or in class list!!" );
587 _logger.myLog( getWindow(), ((HprofRoot)this.getRoots().get(i)).toString() );
588 }
589 }
590
591 if( ( ! MadmapMain.noGUI() ) && (i % 100 == 0)) {
592 progress_bar.setValue(i);
593 getWindow().updateMemoryProgressBar();
594 }
595 }
596
597 if( ! MadmapMain.noGUI() ) {
598 progress_bar.setValue(progress_bar.getMaximum());
599 }
600 _logger.myLog( getWindow(), elapsedTime() + ": analyze: iterative marking complete" );
601
602
603 _marking_stack = null;
604 }
605
606 } catch( Throwable e ) {
607 _logger.myLog( getWindow(), elapsedTime() + ": Exception in iterativeMarking(): " + e );
608 e.printStackTrace();
609 }
610 }
611
612
613 int _maxRecursion = 0;
614 int _currRecursion = 0;
615
616 public long recursiveCollectChildrenSize( HprofHeapCollectable ho ) {
617 ho.setLiveness( true );
618 ho.setRetainedSize( ho.size() );
619 _totalMarkedLive++;
620 long numChildren = ho.children_size();
621 if ( numChildren > 0 ) {
622 long[] curr_children = ho.children();
623
624
625
626
627 for ( int j = 0; j < numChildren; j++ ) {
628 try {
629 long addr = curr_children[ j ];
630 HprofHeapCollectable child = (HprofHeapAllocation) this.getObjects().get( new HprofHeapElement(addr) );
631
632
633 if ( child == null ) {
634
635
636
637 child = (HprofHeapCollectable) this.getClasses().get( new HprofHeapElement(addr) );
638 }
639
640 if ( child == null ) {
641 if ( MadmapMain.verbose() ) {
642 _logger.myLog( getWindow(), "Cannot find child ho.children[" + j + "]: " + Long.toHexString( addr ) + " of parent " + Long.toHexString(ho.addr() ) + " in heap table!!" );
643 _logger.myLog( getWindow(), ho.toString() );
644 }
645 } else {
646 if ( ! child.isAlive() ) {
647 long retSize = recursiveCollectChildrenSize( child );
648 ho.setRetainedSize(ho.getRetainedSize() + retSize);
649 }
650 }
651 } catch ( ClassCastException cce ) {
652 cce.printStackTrace();
653 }
654 }
655 }
656 _currRecursion++;
657 return ho.getRetainedSize();
658 }
659
660
661
662
663 private void buildLiveObjectsHistogram() {
664 Collection<HprofHeapAllocation> hoc = _heap_objects_table.values();
665 Iterator<HprofHeapAllocation> ihoc = hoc.iterator();
666 while( ihoc.hasNext() ) {
667 HprofHeapAllocation ho = ihoc.next();
668 HprofClassElement klassRef = ho.class_addr();
669 assert klassRef != null : "should not be null";
670 try {
671
672
673 if ( klassRef != null ) {
674 klassRef.setInstanceCount( klassRef.getInstanceCount() + 1 );
675 klassRef.setInstanceSize( klassRef.getInstanceSize() + ho.size() );
676
677 } else {
678 _logger.myLog( getWindow(), "no klass for " + Long.toHexString( klassRef.addr() ) + ho );
679 }
680 } catch ( Exception e ) {
681 _logger.myLog( getWindow(), "### Exception during basic type reconciliation " );
682 if ( ho != null ) {
683 _logger.myLog( getWindow(), ho.toString() );
684 }
685 _logger.myLog( getWindow(), "### klassRef = " + klassRef );
686 e.printStackTrace();
687 }
688 }
689
690 java.util.ArrayList<HprofClassElement> classList = new java.util.ArrayList<HprofClassElement>();
691 classList.addAll(this.getClasses().values());
692 Collections.sort(classList, new SizeComparator());
693
694
695 Iterator<HprofClassElement> icl = classList.iterator();
696 while( icl.hasNext() ) {
697 HprofClassElement hk = icl.next();
698 int ic = hk.getInstanceCount();
699 if (ic == 0) {
700 icl.remove();
701 if ( MadmapMain.runDump() ) {
702 System.out.println( "Removed class with 0 instances: " + hk.className() + "@" + Long.toHexString(hk.addr()));
703 }
704 }
705 }
706
707 TreeSet threadSet = new TreeSet( new ThreadComparator() );
708 threadSet.addAll( (Collection<HprofThreadData>)_threads_list.values() );
709
710 if ( ! MadmapMain.noGUI() ) {
711 getWindow().addLiveHeapTab( classList, _liveObjectsSize );
712 getWindow().addThreadsTab( threadSet );
713 }
714
715
716 _logger.myLog( getWindow(), "Summary of live objects sorted by cumulative size: " );
717 _logger.myLog( getWindow(), " " );
718 _logger.myLog( getWindow(), "Size\t\tPct of Live Size\t\tCount\t\tClass@ClassAddr" );
719 _logger.myLog( getWindow(), "==================================================================================================== " );
720
721 Iterator<HprofClassElement> ihoc3 = classList.iterator();
722 while( ihoc3.hasNext() ) {
723 HprofClassElement hk = ihoc3.next();
724 int ic = hk.getInstanceCount();
725 long is = hk.getInstanceSize();
726
727 float pctLiveSize = (float) is / (float) _liveObjectsSize * (float)100.0;
728
729 if ( ic > 0 ) {
730 _logger.myLog( getWindow(), is + "\t\t" + pctLiveSize + "%\t\t" + ic + "\t\t" + hk.className() + "@" + Long.toHexString( hk.addr() ) );
731 }
732 }
733 _logger.myLog( getWindow(), "==================================================================================================== " );
734 }
735
736
737
738
739
740
741
742 void sortOnRetainedSize( Vector rootSet, String description) {
743 JProgressBar progress_bar = null;
744 int i = 0;
745 try {
746 Iterator<HprofRoot> irs = rootSet.iterator();
747
748 if ( ! MadmapMain.noGUI() ) {
749 progress_bar = getWindow().getProgressBar();
750 getWindow().getLabelForProgressBar().setText("Retained Size: " + description);
751 progress_bar.setMinimum(0);
752 progress_bar.setMaximum(rootSet.size() - 1);
753 progress_bar.setValue(0);
754 }
755
756 _logger.myLog( getWindow(), elapsedTime() + ": analyze: recursive retained size" );
757
758 while( irs.hasNext() ) {
759 HprofRoot hr = irs.next();
760 HprofHeapCollectable ho;
761
762 ho = (HprofHeapCollectable) this.getClasses().get( new HprofHeapElement(hr.addr()) );
763 if ( ho == null ) {
764 ho = (HprofHeapCollectable) this.getObjects().get( new HprofHeapElement(hr.addr()) );
765 }
766
767 if ( ho != null ) {
768 recursiveCollectChildrenSize( ho );
769 if ( _currRecursion > _maxRecursion ) {
770 _maxRecursion = _currRecursion;
771 }
772 _currRecursion = 0;
773 } else {
774
775 if (hr.addr() != 0 && MadmapMain.verbose() && hr.rootType().equals("<system class>")) {
776 _logger.myLog( getWindow(), "Cannot find system class root[" + Long.toHexString(hr.addr()) + "] in heap table or in class list!!" );
777 _logger.myLog( getWindow(), hr.toString() );
778 }
779 }
780
781 if (( ! MadmapMain.noGUI() ) && (i++ % 100 == 0)) {
782 progress_bar.setValue(i);
783 getWindow().updateMemoryProgressBar();
784 }
785 }
786
787 if( ! MadmapMain.noGUI() ) {
788 progress_bar.setValue(progress_bar.getMaximum());
789 }
790 } catch ( Exception e ) {
791 System.out.println( "Exception while collect children size = " + e );
792 e.printStackTrace();
793 }
794 }
795
796
797
798
799
800 void resetForScanning() {
801
802 for (Enumeration e = this.getObjects().keys() ; e.hasMoreElements() ; ) {
803 Object k = e.nextElement();
804 HprofHeapCollectable ho = (HprofHeapCollectable) this.getObjects().get( k );
805 ho.setLiveness(false);
806 ho.setRetainedSize(0);
807 ho.resetVisited();
808 ho.setClaimed(false);
809 }
810 for (Enumeration e = this.getClasses().keys() ; e.hasMoreElements() ; ) {
811 Object k = e.nextElement();
812 HprofClassElement ho = (HprofClassElement) this.getClasses().get( k );
813 ho.setLiveness(false);
814 ho.setRetainedSize(0);
815 ho.setTotalRetainedSize(0);
816 ho.resetVisited();
817 ho.setClaimed(false);
818 }
819 _leak_guess_table = new ConcurrentHashMap();
820 }
821
822
823
824
825
826
827 HprofHeapCollectable getRefFromAddr( long ref ) {
828
829 HprofHeapCollectable child = (HprofHeapAllocation) this.getObjects().get( new HprofHeapElement( ref ));
830
831 if ( child == null ) {
832 child = (HprofHeapCollectable) this.getClasses().get( new HprofHeapElement(ref) );
833 }
834 if ( MadmapMain.runDump() && child == null ) {
835 System.out.println( "### getRefFromAddr didnt find " + Long.toHexString( ref ));
836 }
837 return child;
838 }
839
840 void accumulateChildrenSize( HprofHeapCollectable ref ) {
841
842 Stack visited = ref.getVisitedStack();
843 if ( visited != null ) {
844 while ( ! visited.empty() ) {
845 HprofHeapCollectable childRef = (HprofHeapCollectable) visited.pop();
846
847 if ( ! childRef.isClaimed() ) {
848 childRef.claim();
849 long childSize = childRef.getRetainedSize();
850 ref.setRetainedSize( ref.getRetainedSize() + childSize);
851 if ( ! (ref.getRetainedSize() < _liveObjectsSize)) {
852 _logger.myLog( getWindow(), "ret size > total live size of " + _liveObjectsSize );
853 _logger.myLog( getWindow(), ref.toString() );
854 }
855 if ( MadmapMain.runDump() ) {
856 System.out.println( "added " + childRef.className() + "@" + Long.toHexString( childRef.addr() ) + "=" + childSize +
857 " to:" + ref.className() + "@" + Long.toHexString( ref.addr() ) + " total size:" + ref.getRetainedSize() );
858 }
859 }
860 }
861 }
862
863 if ( MadmapMain.runDump() ) {
864 System.out.println( "Completed retained size collection " + ref.className() + "@" +
865 Long.toHexString( ref.addr() ) + " total size:" + ref.getRetainedSize() );
866 }
867 assert ref.getRetainedSize() < _liveObjectsSize : "ret size > total live size!";
868 }
869
870 public void iterativeCollectChildrenSize( HprofHeapCollectable ho ) {
871 int markedInThisPass = 0;
872 java.util.Stack _addr_stack = new java.util.Stack();
873
874 _addr_stack.push( ho );
875
876
877 while ( ! _addr_stack.empty() ) {
878
879 HprofHeapCollectable ref = (HprofHeapCollectable)_addr_stack.pop();
880
881
882
883
884 if ( ref != null ) {
885 ref.setLiveness( true );
886
887
888 long numChildren = ref.children_size();
889
890 if (( numChildren > 0 ) && (ref.getRetainedSize() == 0)) {
891 int start = ref.getVisitedCount();
892 int i = 0;
893 long allChildren[] = ref.children();
894
895 if ( MadmapMain.runDump() ) {
896 System.out.println( "scanned " + (markedInThisPass++) + " curr:" + ref.className() + "@" +
897 Long.toHexString( ref.addr() ) + " already visited " + start + " children of " + numChildren);
898 }
899
900 if ( start < numChildren ) {
901 boolean pushedRef = false;
902 for ( i = ((int)numChildren - start); i > 0; i-- ) {
903
904
905 HprofHeapCollectable childRef = getRefFromAddr( allChildren[i - 1] );
906
907
908 if ( (childRef != null) && (! childRef.isAlive())) {
909 if ( pushedRef == false) {
910 _addr_stack.push( ref );
911 pushedRef = true;
912 if ( MadmapMain.runDump() ) {
913 System.out.println( " ref: " + ref.className() + "@" + Long.toHexString( ref.addr() ));
914 }
915 }
916
917 _addr_stack.push( childRef );
918 ref.visited( childRef );
919
920 if ( MadmapMain.runDump() ) {
921 System.out.println( "pushing ref: " + ref.className() + "@" + Long.toHexString( ref.addr() ) + "->" +
922 Long.toHexString( childRef.addr() ));
923 }
924 } else {
925 if ( MadmapMain.runDump() ) {
926 System.out.println( "child already live: ref: " + ref.className() + "@" + Long.toHexString( ref.addr() ) + "->" +
927 Long.toHexString( childRef.addr() ));
928 }
929 }
930 }
931
932
933
934 if ( pushedRef == false ) {
935
936 if ( MadmapMain.runDump() ) {
937 System.out.println( "ref: " + ref.className() + "@" + Long.toHexString( ref.addr() ) + ": all children are visited" );
938 }
939
940 if (ref.getRetainedSize() == 0 ) {
941
942 ref.setRetainedSize( ref.size() );
943 accumulateChildrenSize( ref );
944 }
945 }
946 } else {
947 assert (ref.getRetainedSize() == 0) : "resetting retained size?";
948
949 if ( (start == numChildren) && ( ref.getRetainedSize() == 0 ) ) {
950
951 ref.setRetainedSize( ref.size() );
952 accumulateChildrenSize( ref );
953 } else {
954
955
956
957 }
958 }
959 } else {
960 if ( ref.getRetainedSize() == 0 ) {
961
962 ref.setRetainedSize( ref.size() );
963 } else {
964
965 }
966
967 }
968 } else {
969 _logger.myLog( getWindow(), "markChildren: ====================================================================================" );
970 _logger.myLog( getWindow(), "markChildren: pushed null descending from root " + Long.toHexString(ho.addr()) + " in heap table!!" );
971 _logger.myLog( getWindow(), ho.toString() );
972 _logger.myLog( getWindow(), "markChildren: ====================================================================================" );
973 }
974 }
975
976 assert _addr_stack.empty() : "exiting markChildren but _marking_stack is not empty! " ;
977 }
978
979 public void iterativeCollectChildrenSizeOld( HprofHeapCollectable ho ) {
980 int markedInThisPass = 0;
981 java.util.Stack _addr_stack = new java.util.Stack();
982
983 if ( MadmapMain.runDump() ) {
984 System.out.println( "Marking root: " + ho.className() + "@" + Long.toHexString( ho.addr() ) );
985 }
986
987 _addr_stack.push( ho );
988
989
990 while ( ! _addr_stack.empty() ) {
991
992
993 HprofHeapCollectable ref = (HprofHeapCollectable)_addr_stack.pop();
994
995 if ( ref != null ) {
996 ref.setLiveness( true );
997
998
999 long numChildren = ref.children_size();
1000 int start = ref.getVisitedCount();
1001
1002 if ( MadmapMain.runDump() ) {
1003 System.out.println( "scanned " + (markedInThisPass++) + " curr:" + ref.className() + "@" +
1004 Long.toHexString( ref.addr() ) + " already visited children " + start + " of " + numChildren);
1005 }
1006
1007 if ( numChildren > 0 ) {
1008 int i = 0;
1009 for ( i = start; i < numChildren; i++ ) {
1010
1011
1012 HprofHeapCollectable childRef = getRefFromAddr( ref.children()[i] );
1013 if ( ! childRef.isAlive() ) {
1014
1015 _addr_stack.push( ref );
1016 _addr_stack.push( childRef );
1017 ref.visited( childRef );
1018
1019 if ( MadmapMain.runDump() ) {
1020 System.out.println( " ref: " + ref.className() + "@" + Long.toHexString( ref.addr() ) + "->" +
1021 Long.toHexString( childRef.addr() ));
1022 }
1023 break;
1024 } else {
1025 if ( MadmapMain.runDump() ) {
1026 System.out.println( "child already live: ref: " + ref.className() + "@" + Long.toHexString( ref.addr() ) + "->" +
1027 Long.toHexString( childRef.addr() ));
1028 }
1029 }
1030 }
1031
1032
1033 if ( i == numChildren ) {
1034 if ( ref.getRetainedSize() == 0 ) {
1035 ref.setRetainedSize( ref.size() );
1036 }
1037
1038 Stack visited = ref.getVisitedStack();
1039 if ( visited != null ) {
1040 while ( ! visited.empty() ) {
1041 HprofHeapCollectable childRef = (HprofHeapCollectable) visited.pop();
1042 long childSize = childRef.getRetainedSize();
1043 ref.setRetainedSize( ref.getRetainedSize() + childSize);
1044 if ( MadmapMain.runDump() ) {
1045 System.out.println( "added " + childRef.className() + "@" + Long.toHexString( childRef.addr() ) + "=" + childSize +
1046 " to:" + ref.className() + "@" + Long.toHexString( ref.addr() ) + " total size:" + ref.getRetainedSize() );
1047 }
1048 }
1049
1050 if ( MadmapMain.runDump() ) {
1051 System.out.println( "Completed retained size collection " + ref.className() + "@" +
1052 Long.toHexString( ref.addr() ) + " total size:" + ref.getRetainedSize() );
1053 }
1054
1055 } else {
1056 if ( MadmapMain.runDump() ) {
1057 System.out.println( "visited stack is empty: " + ref.className() + "@" + Long.toHexString( ref.addr() ) );
1058 }
1059 }
1060 }
1061 } else {
1062
1063 ref.setRetainedSize( ref.size() );
1064
1065
1066
1067 }
1068 } else {
1069 _logger.myLog( getWindow(), "markChildren: ====================================================================================" );
1070 _logger.myLog( getWindow(), "markChildren: pushed null descending from root " + Long.toHexString(ho.addr()) + " in heap table!!" );
1071 _logger.myLog( getWindow(), ho.toString() );
1072 _logger.myLog( getWindow(), "markChildren: ====================================================================================" );
1073 }
1074 }
1075
1076 assert _addr_stack.empty() : "exiting markChildren but _marking_stack is not empty! " ;
1077 }
1078
1079
1080 void iterativeSortOnRetainedSize( Vector rootSet, String description) {
1081 JProgressBar progress_bar = null;
1082 int i = 0;
1083 Iterator<HprofRoot> irs = rootSet.iterator();
1084
1085 _logger.myLog( getWindow(), elapsedTime() + ": analyze: iterative retained size by: " + description );
1086
1087 if ( ! MadmapMain.noGUI() ) {
1088 progress_bar = getWindow().getProgressBar();
1089 getWindow().getLabelForProgressBar().setText("Retained Size: " + description);
1090 progress_bar.setMinimum(0);
1091 progress_bar.setMaximum(rootSet.size() - 1);
1092 progress_bar.setValue(0);
1093 }
1094
1095 try {
1096 while( irs.hasNext() ) {
1097 HprofRoot hr = irs.next();
1098 HprofHeapCollectable ho;
1099
1100 assert hr != null : "root should not be null";
1101
1102 ho = (HprofHeapCollectable) this.getClasses().get( new HprofHeapElement(hr.addr()) );
1103 if ( ho == null ) {
1104 ho = (HprofHeapCollectable) this.getObjects().get( new HprofHeapElement( hr.addr()) );
1105 }
1106
1107 if ( ho != null ) {
1108 if ( MadmapMain.testFeature() == true ) {
1109 iterativeCollectChildrenSizeOld( ho );
1110 } else {
1111 iterativeCollectChildrenSize( ho );
1112 }
1113 } else {
1114
1115 if (hr.addr() != 0 && MadmapMain.verbose() && hr.rootType().equals("<system class>")) {
1116 _logger.myLog( getWindow(), "Cannot find system class root[" + Long.toHexString(hr.addr()) + "] in heap table or in class list!!" );
1117 _logger.myLog( getWindow(), hr.toString() );
1118 }
1119 }
1120
1121 if( ( ! MadmapMain.noGUI() ) && (i++ % 100 == 0)) {
1122 progress_bar.setValue(i);
1123 getWindow().updateMemoryProgressBar();
1124 }
1125 }
1126
1127 if( ! MadmapMain.noGUI() ) {
1128 progress_bar.setValue(progress_bar.getMaximum());
1129 }
1130 _logger.myLog( getWindow(), elapsedTime() + ": analyze: iterative retained size complete" );
1131 } catch( Throwable e ) {
1132 _logger.myLog( getWindow(), elapsedTime() + ": iterative retained size: " + e );
1133 e.printStackTrace();
1134 }
1135 }
1136
1137 public void displayRetainedSortResults(String description) {
1138
1139 {
1140 ArrayList<HprofHeapAllocation> objList = new java.util.ArrayList<HprofHeapAllocation>();
1141
1142 ArrayList<HprofHeapAllocation> retModel = new ArrayList<HprofHeapAllocation>();
1143
1144
1145 for (Enumeration e = this.getObjects().keys() ; e.hasMoreElements() ; ) {
1146 Object k = e.nextElement();
1147 HprofHeapAllocation ho = this.getObjects().get( k );
1148 long rs = ho.getRetainedSize();
1149 float pctLiveSize = ((float) rs / (float) _liveObjectsSize) * (float)100.0;
1150
1151 if ( pctLiveSize > 10.0 ) {
1152 objList.add( ho );
1153 }
1154 }
1155 Collections.sort(objList, new RetainedSizeComparator());
1156
1157 _logger.myLog( getWindow(), "Live objects sorted by cumulative retained size by: " + description );
1158 _logger.myLog( getWindow(), " " );
1159 _logger.myLog( getWindow(), "Retained Size\tPct of Live Size\tClass@ObjAddr" );
1160 _logger.myLog( getWindow(), "==================================================================================================== " );
1161
1162 Iterator<HprofHeapAllocation> ihoc3 = objList.iterator();
1163 while( ihoc3.hasNext() ) {
1164 HprofHeapAllocation hk = ihoc3.next();
1165 long rs = hk.getRetainedSize();
1166 float pctLiveSize = ((float) rs / (float) _liveObjectsSize) * (float)100.0;
1167 boolean haveThread = false;
1168 HprofThreadData thd = null;
1169
1170
1171 if ( hk.className().equals("java.lang.Thread") ) {
1172 thd = (HprofThreadData) getThreads().get( (int) hk.addr() );
1173 if ( thd != null ) {
1174 haveThread = true;
1175 }
1176 }
1177
1178 {
1179
1180 HprofClassElement thisClass = (HprofClassElement) hk.getActualClass();
1181 thisClass.setTotalRetainedSize( thisClass.getTotalRetainedSize() + hk.getRetainedSize() );
1182 }
1183
1184
1185 {
1186 int stackId = hk.getStackTrace();
1187 HprofStackTraceData std = null;
1188 if ( stackId != 0 ) {
1189 std = (HprofStackTraceData)getStackTraces().get(stackId);
1190 }
1191 List stkTrc = null;
1192 if ( std != null ) {
1193 stkTrc = std.getStackVector();
1194 }
1195
1196
1197 if ( (stkTrc != null) && (stkTrc.size() == 1) && ((String)stkTrc.get(0)).equals("<empty>") ) {
1198
1199
1200 } else {
1201
1202
1203
1204 long[] child_refs = hk.children();
1205 boolean notLeak = false;
1206 if ( child_refs != null ) {
1207 for ( int i = 0; i < child_refs.length; i++ ) {
1208 HprofHeapCollectable child = getRefFromAddr( child_refs[i] );
1209 if (child != null) {
1210 long rsc = child.getRetainedSize();
1211 float childPctLiveSize = ((float) rsc / (float) _liveObjectsSize) * (float)100.0;
1212 if ( childPctLiveSize > (pctLiveSize - (float)5.0) ) {
1213 notLeak = true;
1214 }
1215 } else {
1216 notLeak = true;
1217 }
1218 }
1219 if (! notLeak ) {
1220 getGuesses().put( hk.addr(), (new Boolean(true)) );
1221 }
1222 }
1223 StringBuffer objDetail = new StringBuffer(rs + "\t" + pctLiveSize + "%\t" + "\t" + hk.className() + "@" + Long.toHexString( hk.addr()));
1224 if ( haveThread == true ) {
1225 objDetail.append(" [ " + thd.name() + " ]");
1226 }
1227 if (! notLeak ) {
1228 objDetail.append("\t *** Leak Guess ***");
1229 }
1230 _logger.myLog( getWindow(), objDetail.toString() );
1231
1232 if (stkTrc != null) {
1233 for (int j = 0; j < stkTrc.size(); j++ ) {
1234 String s = (String) stkTrc.get( j );
1235 _logger.myLog( getWindow(), " " + s );
1236 }
1237 }
1238 retModel.add( hk );
1239 }
1240 }
1241 }
1242
1243 if ( ! MadmapMain.noGUI() ) {
1244 getWindow().addRetainedHeapTab( this, retModel, _liveObjectsSize, description );
1245 }
1246 }
1247
1248 _logger.myLog( getWindow(), "==================================================================================================== " );
1249 }
1250
1251
1252 public void doRetainedByClass() {
1253 for (int i = 0; i < _rootDescNames.length; i++) {
1254 int verifyRoots = getRoots().size();
1255 _logger.myLog( getWindow(), "==================================================================================================== " );
1256 Collections.sort(getRoots(), new RootComparator(_rootHprofNames[i]));
1257 assert verifyRoots == getRoots().size() : "roots sort is messed up";
1258
1259 String description = _rootHprofNames[i];
1260
1261
1262 {
1263 ArrayList<HprofHeapCollectable> classList = new java.util.ArrayList<HprofHeapCollectable>();
1264
1265
1266 for (Enumeration e = this.getClasses().keys() ; e.hasMoreElements() ; ) {
1267 Object k = e.nextElement();
1268 HprofHeapCollectable ho = (HprofHeapCollectable) this.getClasses().get( k );
1269 long rs = ho.getRetainedSize();
1270 float pctLiveSize = ((float) rs / (float) _liveObjectsSize) * (float)100.0;
1271
1272 if ( pctLiveSize > 10.0 ) {
1273 classList.add( ho );
1274 }
1275 }
1276
1277 Collections.sort(classList, new CumulativeRetainedSizeComparator());
1278
1279 ArrayList<HprofHeapCollectable> classRetModel = new ArrayList<HprofHeapCollectable>();
1280
1281 _logger.myLog( getWindow(), "Classes sorted by cumulative retained size by: " + description );
1282 _logger.myLog( getWindow(), " " );
1283 _logger.myLog( getWindow(), "Retained Size\tPct of Live Size\tInstance Count\tClassName@ClassAddr" );
1284 _logger.myLog( getWindow(), "==================================================================================================== " );
1285
1286 Iterator<HprofHeapCollectable> ihoc = classList.iterator();
1287 while( ihoc.hasNext() ) {
1288 HprofHeapCollectable hk = ihoc.next();
1289 classRetModel.add( hk );
1290 }
1291
1292 if ( ! MadmapMain.noGUI() ) {
1293 getWindow().addRetainedByClassTab( this, classRetModel, _liveObjectsSize, description );
1294 }
1295 }
1296 }
1297 }
1298
1299
1300
1301 String[] _rootDescNames = {
1302 "Classes",
1303 "Threads",
1304 "Java stack",
1305 "JNI global refs"
1306 };
1307
1308 String[] _rootHprofNames = {
1309 "<system class>",
1310 "<thread>",
1311 "<Java stack>",
1312 "<JNI global ref>"
1313 };
1314
1315
1316
1317
1318
1319
1320 void reconcileBasicTypeArrays() {
1321 Collection<HprofClassElement> hoc = this.getClasses().values();
1322 Iterator<HprofClassElement> ihoc = hoc.iterator();
1323
1324 while( ihoc.hasNext() ) {
1325 HprofClassElement hc = ihoc.next();
1326 String nm = hc.className();
1327
1328 if (( nm == "boolean[]" ) || (nm == "[Z")) {
1329 boolArrayKlass = hc;
1330 } else if (( nm == "byte[]" ) || (nm == "[B")) {
1331 byteArrayKlass = hc;
1332 } else if (( nm == "char[]" ) || (nm == "[C")) {
1333 charArrayKlass = hc;
1334 } else if (( nm == "short[]" ) || (nm == "[S")) {
1335 shortArrayKlass = hc;
1336 } else if (( nm == "int[]" ) || (nm == "[I")) {
1337 intArrayKlass = hc;
1338 } else if (( nm == "long[]" ) || (nm == "[J")) {
1339 longArrayKlass = hc;
1340 } else if (( nm == "float[]" ) || (nm == "[F")) {
1341 floatArrayKlass = hc;
1342 } else if (( nm == "double[]" ) || (nm == "[D")) {
1343 doubleArrayKlass = hc;
1344 }
1345 }
1346 }
1347
1348
1349 public void analyze() {
1350 if ( MadmapMain.verbose() ) {
1351 _logger.myLog( getWindow(), elapsedTime() + ": analyze: _roots_list.size() = " + this.getRoots().size() );
1352 }
1353
1354 reconcileBasicTypeArrays();
1355
1356 if (isBinary() && (MadmapMain.printFinalizers() == true)) {
1357 printFinalizers();
1358 }
1359
1360 iterativeMarking();
1361
1362 if ( MadmapMain.verbose() ) {
1363 _logger.myLog( getWindow(), elapsedTime() + ": analyze: build live table " );
1364 }
1365
1366 long build_startTime = System.currentTimeMillis();
1367 buildLiveObjectsTable();
1368 long build_endTime = System.currentTimeMillis();
1369 if ( MadmapMain.verbose() ) {
1370 System.out.println( "Built live graph in " + (build_endTime - build_startTime) + "ms");
1371 }
1372
1373 if ( MadmapMain.verbose() ) {
1374 _logger.myLog( getWindow(), " " );
1375 _logger.myLog( getWindow(), elapsedTime() + ": analyze: build live table complete " );
1376 _logger.myLog( getWindow(), " " );
1377 }
1378
1379 if ( MadmapMain.runSystemGC() ) {
1380 _logger.myLog( getWindow(), elapsedTime() + ": analyze: System.gc() for footprint analysis " );
1381 System.gc();
1382 _logger.myLog( getWindow(), elapsedTime() + ": analyze: System.gc() done " );
1383 }
1384
1385 _logger.myLog( getWindow(), " " );
1386 _logger.myLog( getWindow(), "Total number of types: " + ( this.getClasses().size() ));
1387
1388
1389 buildLiveObjectsHistogram();
1390 if ( !isBinary() && (MadmapMain.printFinalizers() == true)) {
1391 printFinalizers();
1392 }
1393
1394 {
1395
1396 resetForScanning();
1397
1398 int verifyRoots = getRoots().size();
1399
1400 for (int i = 0; i < _rootDescNames.length; i++) {
1401 _logger.myLog( getWindow(), "==================================================================================================== " );
1402 Collections.sort(getRoots(), new RootComparator(_rootHprofNames[i]));
1403 assert verifyRoots == getRoots().size() : "roots sort is messed up";
1404 if ( MadmapMain.runRecursiveChildrenSize() == true ) {
1405 sortOnRetainedSize( getRoots(), _rootDescNames[i] );
1406 } else {
1407 iterativeSortOnRetainedSize( getRoots(), _rootDescNames[i] );
1408 }
1409 displayRetainedSortResults( _rootDescNames[i] );
1410 resetForScanning();
1411 }
1412 }
1413 _logger.myLog( getWindow(), elapsedTime() + ": Analysis complete." );
1414
1415 }
1416
1417 public MainWindow getWindow() { return _window; }
1418
1419 public Madmap( String name, MainWindow theWindow ) {
1420 _window = theWindow;
1421 preinit( name );
1422 }
1423
1424 public Madmap( File inputFile, MainWindow theWindow ) {
1425 String name;
1426 _window = theWindow;
1427 try {
1428 name = inputFile.getCanonicalPath();
1429 } catch (IOException e) {
1430 System.out.println("Something wrong with file from gui");
1431 e.printStackTrace();
1432 return;
1433 }
1434 preinit( name );
1435 }
1436
1437 public Madmap( String name ) {
1438 preinit( name );
1439 }
1440
1441 public static boolean isBinaryDump(String name) {
1442 FileInputStream fis = null;
1443 DataInputStream dis;
1444 BufferedInputStream bis;
1445 byte[] rawBytes = new byte[ 18 ];
1446 byte b = -1;
1447
1448 try {
1449 fis = new FileInputStream( name );
1450 bis = new BufferedInputStream( fis );
1451 dis = new DataInputStream( bis );
1452
1453
1454 int bytesRead = dis.read( rawBytes );
1455 b = dis.readByte();
1456 dis.close();
1457 } catch (IOException e) {
1458 System. out. println ( " Exception while examining file type: " + e );
1459 e.printStackTrace();
1460 System.exit(0);
1461 }
1462
1463 String header = new String( rawBytes );
1464 if ((header.equals ( "JAVA PROFILE 1.0.1" ) ||
1465 header.equals ( "JAVA PROFILE 1.0.2" )) && (b == 0)) {
1466 return true;
1467 }
1468 return false;
1469
1470 }
1471
1472 private void preinit( String name ) {
1473 if (MadmapMain.verbose()) {
1474 System.out.println( "Opening file: " + name );
1475 }
1476 _fileName = name;
1477 _isBinary = Madmap.isBinaryDump( _fileName );
1478
1479
1480 if (_isBinary) {
1481 return;
1482 }
1483
1484
1485
1486
1487 if ( MadmapMain.jdk14_compatible() ) {
1488 boolArrayKlass = new HprofClassElement( (long) 999, "bool[]" );
1489 byteArrayKlass = new HprofClassElement( (long) 998, "byte[]" );
1490 charArrayKlass = new HprofClassElement( (long) 997, "char[]" );
1491 shortArrayKlass = new HprofClassElement( (long) 996, "short[]" );
1492 intArrayKlass = new HprofClassElement( (long) 995, "int[]" );
1493 longArrayKlass = new HprofClassElement( (long) 994, "long[]" );
1494 floatArrayKlass = new HprofClassElement( (long) 993, "float[]" );
1495 doubleArrayKlass = new HprofClassElement( (long) 992, "double[]" );
1496
1497 _class_list.put( boolArrayKlass, boolArrayKlass );
1498 _class_list.put( byteArrayKlass, byteArrayKlass );
1499 _class_list.put( charArrayKlass, charArrayKlass );
1500 _class_list.put( shortArrayKlass, shortArrayKlass );
1501 _class_list.put( intArrayKlass, intArrayKlass );
1502 _class_list.put( longArrayKlass, longArrayKlass );
1503 _class_list.put( floatArrayKlass, floatArrayKlass );
1504 _class_list.put( doubleArrayKlass, doubleArrayKlass );
1505 }
1506 }
1507 }