1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package net.sf.madmap;
16
17 import java.io.*;
18 import java.net.*;
19 import java.util.*;
20 import java.util.concurrent.*;
21
22 public class BinaryDumpReader implements IHprofReader {
23 String _fileName;
24 FileInputStream _fis;
25 DataInputStream _dis;
26 BufferedInputStream _bis;
27
28 int _identifierSize = 0;
29 boolean _done;
30 HashMap<Long,String> _stringTable = new HashMap<Long,String>();
31
32 Madmap _owner = null;
33
34 ConcurrentHashMap<HprofHeapAllocation,HprofHeapAllocation> _heap_objects_table = null;
35 ConcurrentHashMap _stack_trace_table = null;
36 ConcurrentHashMap _threads_list = null;
37 Vector _roots_list = null;
38 ConcurrentHashMap<HprofClassElement,HprofClassElement> _class_list = null;
39
40 boolean _verbose = false;
41
42 static final int STRING = 1;
43 static final int LOAD_CLASS = 2;
44 static final int UNLOAD_CLASS = 3;
45 static final int STACK_FRAME = 4;
46 static final int STACK_TRACE = 5;
47 static final int HEAP_DUMP = 12;
48 static final int HEAP_DUMP_SEGMENT = 0x1c;
49 static final int HEAP_DUMP_END = 0x2c;
50
51 static final int ROOT_UNKNOWN = -1;
52 static final int ROOT_JNI_GLOBAL = 1;
53 static final int ROOT_JNI_LOCAL = 2;
54 static final int ROOT_JAVA_FRAME = 3;
55 static final int ROOT_NATIVE_STACK = 4;
56 static final int ROOT_STICKY_CLASS = 5;
57 static final int ROOT_THREAD_BLOCK = 6;
58 static final int ROOT_MONITOR_USED = 7;
59 static final int ROOT_THREAD_OBJECT = 8;
60
61 static final int CLASS_DUMP = 0x20;
62 static final int INSTANCE_DUMP = 0x21;
63 static final int OBJ_ARRAY_DUMP = 0x22;
64 static final int PRIM_ARRAY_DUMP = 0x23;
65
66 ILogger _logger;
67 public void setLogger( ILogger logger ) { _logger = logger; }
68
69 public BinaryDumpReader() {}
70
71 public void parse( Madmap owner, String fileName) {
72 _owner = owner;
73 _fileName = fileName;
74 _fis = openHprofFile(_fileName);
75 _bis = new BufferedInputStream( _fis );
76 _dis = new DataInputStream( _bis );
77 _done = false;
78
79 _heap_objects_table = owner.getObjects();
80 _stack_trace_table = owner.getStackTraces();
81 _threads_list = owner.getThreads();
82 _roots_list = owner.getRoots();
83 _class_list = owner.getClasses();
84 go();
85 }
86
87 public static FileInputStream openHprofFile(String fileName)
88 {
89 FileInputStream fis;
90
91 try {
92 fis = new FileInputStream(fileName);
93 return fis;
94 } catch ( Exception ie ) {
95 System. out. println ( "Error opening file : Caught " + ie );
96 ie.printStackTrace();
97 }
98 return null;
99 }
100
101
102 long getIdentifier() throws IOException {
103 if ( _identifierSize == 4 ) {
104 return (long)_dis.readInt();
105 } else if ( _identifierSize == 8 ) {
106 return _dis.readLong();
107 } else {
108 System. out. println ( "Unsupported _identifierSize = " + _identifierSize );
109 System.exit(-1);
110 }
111 return 0;
112 }
113
114
115 public void handleString() throws java.io.IOException {
116 int time = _dis.readInt();
117 int length = _dis.readInt();
118
119 if (MadmapMain.runDump()) {
120 System.out.println("length=" + length + " time=" + time );
121 }
122
123 long stringId = getIdentifier();
124 byte[] rawBytes = new byte[ length - _identifierSize ];
125
126 int bytesRead = _dis.read( rawBytes );
127 String body = new String( rawBytes );
128
129 _stringTable.put(stringId, body.intern());
130 if (MadmapMain.runDump()) {
131 System. out. println ( "String: " + Long.toHexString( stringId ) + " " + body );
132 }
133 }
134
135 int _totalLoadClass = 0;
136 int _totalClass = 0;
137
138 public void handleLoadClass() throws java.io.IOException {
139 int time = _dis.readInt();
140 int length = _dis.readInt();
141
142 int serialNum = _dis.readInt();
143 long objId = getIdentifier();
144 int stkTrc = _dis.readInt();
145 long classNameStringId = getIdentifier();
146
147 String className = (String) _stringTable.get(classNameStringId);
148 assert className != null : "no class name?";
149 className = className.intern();
150
151 ++_totalLoadClass;
152 if (MadmapMain.runDump()) {
153 System. out. println ( "Load Class: " + Long.toHexString( objId ) + " " + className + " " + (_totalLoadClass));
154 }
155
156 HprofClassElement loadClass = new HprofBinClassElement(objId, className);
157 _class_list.put(loadClass, loadClass);
158 }
159
160 void handlePrimArray() throws java.io.IOException {
161 long id = getIdentifier();
162 int stk = _dis.readInt();
163 int sz = _dis.readInt();
164 byte typ = _dis.readByte();
165
166 updateSizeRead(sz);
167
168 if (MadmapMain.runDump()) {
169 System. out. println ( "prim array: 0x" + Long.toHexString( id ) + " stk: " + stk + " sz: " + sz + " type: " + typ );
170 }
171 int typeSize = BasicTypeInfo.DUMMY.get(typ).getSize();
172
173 for ( int i = 0; i<(sz * typeSize); i++ ) {
174 byte b = _dis.readByte();
175 }
176
177 HprofArrayObject thisArray = new HprofArrayObject(id, BasicTypeInfo.DUMMY.get(typ).getName(),
178 stk, (sz*typeSize), sz, Madmap.getFakeArrayClass(BasicTypeInfo.DUMMY.get(typ).getName()), null);
179 _heap_objects_table.put(thisArray, thisArray);
180 }
181
182 void handleObjArray() throws java.io.IOException {
183 long id = getIdentifier();
184 int stk = _dis.readInt();
185 int sz = _dis.readInt();
186 long classId = getIdentifier();
187 ArrayList<Long> elems = new ArrayList<Long>();
188
189 updateSizeRead(sz);
190
191 for (int i=0; i<sz; i++) {
192 long ref = getIdentifier();
193
194 if (ref != 0) {
195 elems.add(ref);
196 }
197 }
198
199 HprofBinClassElement theClass = (HprofBinClassElement)_class_list.get(new HprofHeapElement(classId));
200
201
202
203 if (theClass == null) {
204 if (MadmapMain.runDump()) {
205 System. out. println ("### obj array: 0x" + Long.toHexString(id) + " cant find obj array class 0x" + Long.toHexString(classId));
206 }
207 String tmpName = "OBJECT_ARRAY";
208 theClass = new HprofBinClassElement(classId, tmpName);
209 _class_list.put(theClass, theClass);
210 }
211
212 if (MadmapMain.runDump()) {
213 System. out. println ( "obj array: 0x" + Long.toHexString( id ) + " sz: " + sz + " nelems: " +
214 elems.size() + " classId: 0x" + Long.toHexString(classId) + " " + theClass.className());
215 }
216
217 HprofArrayObject thisArray = new HprofArrayObject(id, theClass.className(), stk, (sz*_identifierSize), elems.size(), theClass, elems);
218 _heap_objects_table.put(thisArray, thisArray);
219 }
220
221
222 void handleObjInstance() throws java.io.IOException {
223 long id = getIdentifier();
224 int stk = _dis.readInt();
225 long classId = getIdentifier();
226 int sz = _dis.readInt();
227
228
229 HprofBinClassElement theClass = (HprofBinClassElement)_class_list.get(new HprofHeapElement(classId));
230
231 assert theClass != null : "no class for obj " + id;
232
233 ArrayList<Byte> type_info = theClass.getNonStaticTypeInfo();
234 long instanceSize = theClass.instanceSize();
235
236 if (MadmapMain.runDump()) {
237 System. out. println ( "obj instance: 0x" + Long.toHexString( id ) + " stk: " +
238 Long.toHexString(stk) + " sz: " + sz + " class: " + theClass.className() +
239 " inst sz from class: " + instanceSize + " type:" + type_info);
240 }
241
242 ArrayList names = null;
243 ArrayList refs = null;
244
245 if (type_info != null && type_info.size() > 0) {
246 names = new ArrayList();
247 refs = new ArrayList();
248 int refCounter = 0;
249 for (int i=0; i<type_info.size(); i++) {
250 byte typeCode = type_info.get(i);
251 if (typeCode == 2) {
252 long ref = getIdentifier();
253 if (ref != 0) {
254 refs.add(ref);
255 names.add(theClass.nonstatic_field_names().get(refCounter));
256 }
257 refCounter++;
258 } else {
259
260 int fieldSize = BasicTypeInfo.DUMMY.get((int)typeCode).getSize();
261 for ( int j = 0; j<fieldSize; j++ ) {
262 byte entryData = _dis.readByte();
263 }
264 }
265 }
266 }
267
268 HprofObject obj = new HprofObject( id, theClass.className(), theClass, sz, 0, names, refs);
269 _heap_objects_table.put(obj, obj);
270
271
272 if (names != null && names.size() > 0) {
273 obj.set_member_name_indexes(theClass.setNonstaticFieldNames(names));
274 }
275
276 if ( !MadmapMain.noGUI()) {
277 _owner.getWindow().getProgressBar().setValue(updateSizeRead(sz));
278 _owner.getWindow().updateMemoryProgressBar();
279 }
280 }
281
282
283
284
285
286
287
288
289 void handleClass() throws java.io.IOException {
290 long classId = getIdentifier();
291 int stk = _dis.readInt();
292 long superClassId = getIdentifier();
293 long loaderId = getIdentifier();
294 long signersId = getIdentifier();
295 long protDomainId = getIdentifier();
296 long res1 = getIdentifier();
297 long res2 = getIdentifier();
298 int instanceSize = _dis.readInt();
299 long classNameStringId;
300
301 ArrayList<Byte> instanceFieldTypes = null;
302 ArrayList<String> instanceFieldNames = null;
303
304
305 short cpCount = _dis.readShort();
306 for ( int i = 0; i < cpCount; i++ ) {
307 short idx = _dis.readShort();
308 byte b = _dis.readByte();
309 int sz = BasicTypeInfo.DUMMY.get((int)b).getSize();
310 for ( int j = 0; j<sz; j++ ) {
311 byte entryData = _dis.readByte();
312 }
313 }
314
315 ArrayList staticNames = new ArrayList();
316 ArrayList staticRefs = new ArrayList();
317
318 {
319
320 short staticCount = _dis.readShort();
321 int sz = -1;
322 for ( int i = 0; i < staticCount; i++ ) {
323 long fieldNameStrId = getIdentifier();
324 byte b = _dis.readByte();
325 assert b != 0 : "static field type should not be 0";
326
327
328 if (b == 2) {
329 long ref = getIdentifier();
330 if (ref != 0) {
331 staticNames.add(_stringTable.get(fieldNameStrId));
332 staticRefs.add(ref);
333 }
334 } else {
335 sz = BasicTypeInfo.DUMMY.get((int)b).getSize();
336 for ( int j = 0; j<sz; j++ ) {
337 byte entryData = _dis.readByte();
338 }
339 }
340 }
341 }
342
343 ArrayList nonstaticNames = new ArrayList();
344
345
346 short instanceFieldCount = _dis.readShort();
347 if (instanceFieldCount > 0) {
348 instanceFieldTypes = new ArrayList<Byte>();
349 instanceFieldNames = new ArrayList<String>();
350 for ( int i = 0; i < instanceFieldCount; i++ ) {
351 long fieldNameStrId = getIdentifier();
352 byte b = _dis.readByte();
353
354 assert (b>1) && (b<12) : "unknown typecode in instance field = " + b;
355 String s = _stringTable.get(fieldNameStrId);
356 assert s != null : "String for ref was null: " + fieldNameStrId;
357
358 instanceFieldTypes.add(b);
359 instanceFieldNames.add(s);
360
361
362 if (b == 2) {
363 nonstaticNames.add(s);
364 }
365 }
366 }
367
368 ++_totalClass;
369
370 assert _totalClass<=_totalLoadClass : "_totalClass > _totalLoadClass??";
371
372 HprofBinClassElement theClass = (HprofBinClassElement)_class_list.get(new HprofHeapElement(classId));
373 if (theClass != null ) {
374 theClass.updateLoadClass(stk, instanceSize, superClassId, loaderId, staticNames, staticRefs);
375
376
377 if (instanceFieldTypes != null) {
378 theClass.setNonStaticTypeInfo(instanceFieldTypes);
379 }
380
381 if (nonstaticNames.size() > 0) {
382 theClass.setNonstaticFieldNames(nonstaticNames);
383 }
384
385 if (MadmapMain.runDump()) {
386 System. out. println ("class: 0x" + Long.toHexString( classId ) + " super: 0x" + Long.toHexString(superClassId) + " " +
387 theClass.className() + " instanceFieldCount: " + instanceFieldCount + " instanceFieldTypes: " +
388 instanceFieldTypes + " instanceSize: " + instanceSize + " " + (_totalClass));
389 }
390 } else {
391 assert false : "no load class yet";
392 }
393
394 if (_totalClass == _totalLoadClass) {
395 if (MadmapMain.verbose()) {
396 System. out. println ("Found " + _totalClass + " classes in the heap dump.");
397 }
398 int i = 0;
399
400 if ( !MadmapMain.noGUI()) {
401 _owner.getWindow().getProgressBar().setMaximum((int)_totalLoadClass);
402 _owner.getWindow().getLabelForProgressBar().setText("Building Class Info");
403 }
404
405 Collection<HprofClassElement> hoc = _class_list.values();
406 Iterator<HprofClassElement> ihoc = hoc.iterator();
407 while( ihoc.hasNext() ) {
408 HprofBinClassElement currClass = (HprofBinClassElement) ihoc.next();
409 currClass.buildSuperTypeInfo(_class_list);
410 if ( !MadmapMain.noGUI()) {
411 _owner.getWindow().getProgressBar().setValue(i++);
412 }
413 }
414 }
415 if ( !MadmapMain.noGUI()) {
416 _owner.getWindow().getProgressBar().setMaximum((int)_heapDumpSize);
417 _owner.getWindow().getLabelForProgressBar().setText("Loading Objects");
418 _owner.getWindow().updateMemoryProgressBar();
419 }
420 }
421
422 void handleThreadObject() throws java.io.IOException {
423 long id = getIdentifier();
424 int thdNum = _dis.readInt();
425 int stk = _dis.readInt();
426
427 if (MadmapMain.runDump()) {
428 System. out. println ( "thread object: 0x" + Long.toHexString( id ) + " stk: " + Long.toHexString(stk) + " thdNum: " + thdNum );
429 }
430 _roots_list.add( new HprofRoot(id, "<thread block>"));
431 _threads_list.put( id, new HprofThreadData(null, thdNum, id, null));
432 }
433
434 void handleJNIGlobal() throws java.io.IOException {
435 long id = getIdentifier();
436 long jniId = getIdentifier();
437
438 if (MadmapMain.runDump()) {
439 System. out. println ( "jni global: 0x" + Long.toHexString( id ) + " jniId: " + Long.toHexString(jniId));
440 }
441 _roots_list.add( new HprofRoot(id, "<JNI local ref>"));
442 }
443
444 void handleJNILocal() throws java.io.IOException {
445 long id = getIdentifier();
446 int thdId = _dis.readInt();
447 int frameId = _dis.readInt();
448
449 if (MadmapMain.runDump()) {
450 System. out. println ( "jni local: 0x" + Long.toHexString( id ) + " thdId: " + thdId + " frame: " + frameId);
451 }
452 _roots_list.add( new HprofRoot(id, "<JNI local ref>"));
453 }
454
455
456 void handleJavaFrame() throws java.io.IOException {
457 long id = getIdentifier();
458 int thdId = _dis.readInt();
459 int frameId = _dis.readInt();
460
461 if (MadmapMain.verbose()) {
462 System. out. println ( "handleJavaFrame: 0x" + Long.toHexString( id ) + " thdId: " + thdId + " frame: " + frameId);
463 }
464 _roots_list.add( new HprofRoot(id, "<thread block>"));
465 }
466
467
468 void handleStickyClass() throws java.io.IOException {
469 long id = getIdentifier();
470
471 if (MadmapMain.runDump()) {
472 System. out. println ("sticky class: 0x" + Long.toHexString( id ));
473 }
474 _roots_list.add( new HprofRoot(id, "<system class>"));
475 }
476
477 void handleMonitorUsed() throws java.io.IOException {
478 long id = getIdentifier();
479
480 if (MadmapMain.runDump()) {
481 System. out. println ("handleMonitorUsed: 0x" + Long.toHexString( id ));
482 }
483 _roots_list.add( new HprofRoot(id, "<thread block>"));
484 }
485
486
487 int _heapDumpSize = 0;
488 int _sizeRead = 0;
489
490
491
492
493
494
495
496
497 int updateSizeRead(int sz) {
498 return _sizeRead += sz;
499 }
500
501 public void handleHeapDumpEnd() throws java.io.IOException {
502 int time = _dis.readInt();
503 int length = _dis.readInt();
504
505 }
506
507 public void handleHeapDump() throws java.io.IOException {
508 int time = _dis.readInt();
509 int length = _dis.readInt();
510 int tag = _dis.readByte();
511
512 _heapDumpSize = length;
513 if (MadmapMain.verbose()) {
514 System. out. println ( "Heap Dump time: " + time + " length: " + length );
515 }
516 while ( true ) {
517
518 switch (tag) {
519 case INSTANCE_DUMP:
520 handleObjInstance();
521 break;
522 case PRIM_ARRAY_DUMP:
523 handlePrimArray();
524 break;
525 case OBJ_ARRAY_DUMP:
526 handleObjArray();
527 break;
528 case CLASS_DUMP:
529 handleClass();
530 break;
531 case ROOT_THREAD_OBJECT:
532 handleThreadObject();
533 break;
534 case ROOT_JNI_GLOBAL:
535 handleJNIGlobal();
536 break;
537 case ROOT_JAVA_FRAME:
538 handleJavaFrame();
539 break;
540 case ROOT_JNI_LOCAL:
541 handleJNILocal();
542 break;
543 case ROOT_MONITOR_USED:
544 handleMonitorUsed();
545 break;
546 case ROOT_STICKY_CLASS:
547 handleStickyClass();
548 break;
549 case HEAP_DUMP_SEGMENT:
550 handleHeapDump();
551 break;
552 case HEAP_DUMP_END:
553 handleHeapDumpEnd();
554 System.out.println ( "Found HEAP_DUMP_END " );
555 break;
556 default:
557 System. out. println ( " Unimplemented: 0x" + Integer.toHexString( tag ) );
558 System.exit(1);
559 }
560 try {
561 tag = _dis.readByte();
562 } catch (EOFException e) {
563
564 _done = true;
565 break;
566 }
567 }
568 }
569
570
571 void handleUnloadClass() throws java.io.IOException {
572 int time = _dis.readInt();
573 int length = _dis.readInt();
574 int classId = _dis.readInt();
575
576 if (MadmapMain.verbose()) {
577 System. out. println ("handleUnloadClass: 0x" + Long.toHexString( classId ));
578 }
579 }
580
581 void handleStackTrace() throws java.io.IOException {
582 int time = _dis.readInt();
583 int length = _dis.readInt();
584 int stackTraceId = _dis.readInt();
585 int threadId = _dis.readInt();
586 int numFrames = _dis.readInt();
587
588 if (MadmapMain.runDump()) {
589 System. out. println ("stack trace: 0x" + Long.toHexString( stackTraceId ));
590 }
591 for (int i=0; i<numFrames; i++) {
592 long id = getIdentifier();
593 }
594 }
595
596 void handleStackFrame() throws java.io.IOException {
597 int time = _dis.readInt();
598 int length = _dis.readInt();
599 long stackFrameId = getIdentifier();
600 long methodNameId = getIdentifier();
601 long methodSigId = getIdentifier();
602 long sourceFileNameId = getIdentifier();
603 int classSerialNum = _dis.readInt();
604 int lineNumber = _dis.readInt();
605
606 if (MadmapMain.runDump()) {
607 System. out. println ("stack frame: 0x" + Long.toHexString( stackFrameId ));
608 }
609 }
610
611 public void go() {
612 try {
613
614 byte[] rawBytes = new byte[ 18 ];
615 int bytesRead = _dis.read( rawBytes );
616
617 String header = new String( rawBytes );
618 if ( header.equals ( "JAVA PROFILE 1.0.1" ) || header.equals ( "JAVA PROFILE 1.0.2" )) {
619
620
621 if (MadmapMain.verbose()) {
622 System. out. println ( "Input file " + _fileName + " seems to be a binary heap dump" );
623 }
624
625 byte b = _dis.readByte();
626 assert b == 0 : "not null terminated?";
627
628 _identifierSize = _dis.readInt();
629 long timeStamp = _dis.readLong();
630 System. out. println ( "Timestamp " + timeStamp + " = " + (new Date( timeStamp )) + " ID size=" + _identifierSize);
631
632 while( true && !_done) {
633 int tag = _dis.readByte();
634
635 if (MadmapMain.runDump()) {
636 System.out.println ("read: " + tag);
637 }
638
639 switch ( tag ) {
640 case STRING:
641 handleString();
642 break;
643 case LOAD_CLASS:
644 handleLoadClass();
645 break;
646 case UNLOAD_CLASS:
647 handleUnloadClass();
648 break;
649 case HEAP_DUMP:
650 case HEAP_DUMP_SEGMENT:
651 handleHeapDump();
652 break;
653 case STACK_TRACE:
654 handleStackTrace();
655 break;
656 case STACK_FRAME:
657 handleStackFrame();
658 break;
659 default:
660
661 System.out.println ("unimplemented tag: " + tag);
662 assert false : "should not reach here";
663 }
664 }
665 } else {
666 System. out. println ( "Input file " + _fileName + " does not seem to be a binary heap dump" );
667 }
668
669 } catch (IOException ioe) {
670 System. out. println ( "Error with data file : Caught " + ioe );
671 ioe.printStackTrace();
672 }
673 }
674
675 public static void usage() {
676 System.out.println("");
677 System.out.println("Usage: BinaryDumpReader [options] <filename>");
678 }
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737 }