1 /*
2  * Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  *
23  */
24 
25 package sun.jvm.hotspot.utilities;
26 
27 import java.io.*;
28 import java.nio.channels.*;
29 import java.util.*;
30 import sun.jvm.hotspot.debugger.*;
31 import sun.jvm.hotspot.memory.*;
32 import sun.jvm.hotspot.oops.*;
33 import sun.jvm.hotspot.runtime.*;
34 import sun.jvm.hotspot.classfile.*;
35 
36 /*
37  * This class writes Java heap in hprof binary format. This format is
38  * used by Heap Analysis Tool (HAT). The class is heavily influenced
39  * by 'hprof_io.c' of 1.5 new hprof implementation.
40  */
41 
42 /* hprof binary format: (result either written to a file or sent over
43  * the network).
44  *
45  * WARNING: This format is still under development, and is subject to
46  * change without notice.
47  *
48  * header     "JAVA PROFILE 1.0.2" (0-terminated)
49  * u4         size of identifiers. Identifiers are used to represent
50  *            UTF8 strings, objects, stack traces, etc. They usually
51  *            have the same size as host pointers. For example, on
52  *            Solaris and Win32, the size is 4.
53  * u4         high word
54  * u4         low word    number of milliseconds since 0:00 GMT, 1/1/70
55  * [record]*  a sequence of records.
56  *
57  */
58 
59 /*
60  *
61  * Record format:
62  *
63  * u1         a TAG denoting the type of the record
64  * u4         number of *microseconds* since the time stamp in the
65  *            header. (wraps around in a little more than an hour)
66  * u4         number of bytes *remaining* in the record. Note that
67  *            this number excludes the tag and the length field itself.
68  * [u1]*      BODY of the record (a sequence of bytes)
69  */
70 
71 /*
72  * The following TAGs are supported:
73  *
74  * TAG           BODY       notes
75  *----------------------------------------------------------
76  * HPROF_UTF8               a UTF8-encoded name
77  *
78  *               id         name ID
79  *               [u1]*      UTF8 characters (no trailing zero)
80  *
81  * HPROF_LOAD_CLASS         a newly loaded class
82  *
83  *                u4        class serial number (> 0)
84  *                id        class object ID
85  *                u4        stack trace serial number
86  *                id        class name ID
87  *
88  * HPROF_UNLOAD_CLASS       an unloading class
89  *
90  *                u4        class serial_number
91  *
92  * HPROF_FRAME              a Java stack frame
93  *
94  *                id        stack frame ID
95  *                id        method name ID
96  *                id        method signature ID
97  *                id        source file name ID
98  *                u4        class serial number
99  *                i4        line number. >0: normal
100  *                                       -1: unknown
101  *                                       -2: compiled method
102  *                                       -3: native method
103  *
104  * HPROF_TRACE              a Java stack trace
105  *
106  *               u4         stack trace serial number
107  *               u4         thread serial number
108  *               u4         number of frames
109  *               [id]*      stack frame IDs
110  *
111  *
112  * HPROF_ALLOC_SITES        a set of heap allocation sites, obtained after GC
113  *
114  *               u2         flags 0x0001: incremental vs. complete
115  *                                0x0002: sorted by allocation vs. live
116  *                                0x0004: whether to force a GC
117  *               u4         cutoff ratio
118  *               u4         total live bytes
119  *               u4         total live instances
120  *               u8         total bytes allocated
121  *               u8         total instances allocated
122  *               u4         number of sites that follow
123  *               [u1        is_array: 0:  normal object
124  *                                    2:  object array
125  *                                    4:  boolean array
126  *                                    5:  char array
127  *                                    6:  float array
128  *                                    7:  double array
129  *                                    8:  byte array
130  *                                    9:  short array
131  *                                    10: int array
132  *                                    11: long array
133  *                u4        class serial number (may be zero during startup)
134  *                u4        stack trace serial number
135  *                u4        number of bytes alive
136  *                u4        number of instances alive
137  *                u4        number of bytes allocated
138  *                u4]*      number of instance allocated
139  *
140  * HPROF_START_THREAD       a newly started thread.
141  *
142  *               u4         thread serial number (> 0)
143  *               id         thread object ID
144  *               u4         stack trace serial number
145  *               id         thread name ID
146  *               id         thread group name ID
147  *               id         thread group parent name ID
148  *
149  * HPROF_END_THREAD         a terminating thread.
150  *
151  *               u4         thread serial number
152  *
153  * HPROF_HEAP_SUMMARY       heap summary
154  *
155  *               u4         total live bytes
156  *               u4         total live instances
157  *               u8         total bytes allocated
158  *               u8         total instances allocated
159  *
160  * HPROF_HEAP_DUMP          denote a heap dump
161  *
162  *               [heap dump sub-records]*
163  *
164  *                          There are four kinds of heap dump sub-records:
165  *
166  *               u1         sub-record type
167  *
168  *               HPROF_GC_ROOT_UNKNOWN         unknown root
169  *
170  *                          id         object ID
171  *
172  *               HPROF_GC_ROOT_THREAD_OBJ      thread object
173  *
174  *                          id         thread object ID  (may be 0 for a
175  *                                     thread newly attached through JNI)
176  *                          u4         thread sequence number
177  *                          u4         stack trace sequence number
178  *
179  *               HPROF_GC_ROOT_JNI_GLOBAL      JNI global ref root
180  *
181  *                          id         object ID
182  *                          id         JNI global ref ID
183  *
184  *               HPROF_GC_ROOT_JNI_LOCAL       JNI local ref
185  *
186  *                          id         object ID
187  *                          u4         thread serial number
188  *                          u4         frame # in stack trace (-1 for empty)
189  *
190  *               HPROF_GC_ROOT_JAVA_FRAME      Java stack frame
191  *
192  *                          id         object ID
193  *                          u4         thread serial number
194  *                          u4         frame # in stack trace (-1 for empty)
195  *
196  *               HPROF_GC_ROOT_NATIVE_STACK    Native stack
197  *
198  *                          id         object ID
199  *                          u4         thread serial number
200  *
201  *               HPROF_GC_ROOT_STICKY_CLASS    System class
202  *
203  *                          id         object ID
204  *
205  *               HPROF_GC_ROOT_THREAD_BLOCK    Reference from thread block
206  *
207  *                          id         object ID
208  *                          u4         thread serial number
209  *
210  *               HPROF_GC_ROOT_MONITOR_USED    Busy monitor
211  *
212  *                          id         object ID
213  *
214  *               HPROF_GC_CLASS_DUMP           dump of a class object
215  *
216  *                          id         class object ID
217  *                          u4         stack trace serial number
218  *                          id         super class object ID
219  *                          id         class loader object ID
220  *                          id         signers object ID
221  *                          id         protection domain object ID
222  *                          id         reserved
223  *                          id         reserved
224  *
225  *                          u4         instance size (in bytes)
226  *
227  *                          u2         size of constant pool
228  *                          [u2,       constant pool index,
229  *                           ty,       type
230  *                                     2:  object
231  *                                     4:  boolean
232  *                                     5:  char
233  *                                     6:  float
234  *                                     7:  double
235  *                                     8:  byte
236  *                                     9:  short
237  *                                     10: int
238  *                                     11: long
239  *                           vl]*      and value
240  *
241  *                          u2         number of static fields
242  *                          [id,       static field name,
243  *                           ty,       type,
244  *                           vl]*      and value
245  *
246  *                          u2         number of inst. fields (not inc. super)
247  *                          [id,       instance field name,
248  *                           ty]*      type
249  *
250  *               HPROF_GC_INSTANCE_DUMP        dump of a normal object
251  *
252  *                          id         object ID
253  *                          u4         stack trace serial number
254  *                          id         class object ID
255  *                          u4         number of bytes that follow
256  *                          [vl]*      instance field values (class, followed
257  *                                     by super, super's super ...)
258  *
259  *               HPROF_GC_OBJ_ARRAY_DUMP       dump of an object array
260  *
261  *                          id         array object ID
262  *                          u4         stack trace serial number
263  *                          u4         number of elements
264  *                          id         array class ID
265  *                          [id]*      elements
266  *
267  *               HPROF_GC_PRIM_ARRAY_DUMP      dump of a primitive array
268  *
269  *                          id         array object ID
270  *                          u4         stack trace serial number
271  *                          u4         number of elements
272  *                          u1         element type
273  *                                     4:  boolean array
274  *                                     5:  char array
275  *                                     6:  float array
276  *                                     7:  double array
277  *                                     8:  byte array
278  *                                     9:  short array
279  *                                     10: int array
280  *                                     11: long array
281  *                          [u1]*      elements
282  *
283  * HPROF_CPU_SAMPLES        a set of sample traces of running threads
284  *
285  *                u4        total number of samples
286  *                u4        # of traces
287  *               [u4        # of samples
288  *                u4]*      stack trace serial number
289  *
290  * HPROF_CONTROL_SETTINGS   the settings of on/off switches
291  *
292  *                u4        0x00000001: alloc traces on/off
293  *                          0x00000002: cpu sampling on/off
294  *                u2        stack trace depth
295  *
296  *
297  * A heap dump can optionally be generated as a sequence of heap dump
298  * segments. This sequence is terminated by an end record. The additional
299  * tags allowed by format "JAVA PROFILE 1.0.2" are:
300  *
301  * HPROF_HEAP_DUMP_SEGMENT  denote a heap dump segment
302  *
303  *               [heap dump sub-records]*
304  *               The same sub-record types allowed by HPROF_HEAP_DUMP
305  *
306  * HPROF_HEAP_DUMP_END      denotes the end of a heap dump
307  *
308  */
309 
310 public class HeapHprofBinWriter extends AbstractHeapGraphWriter {
311 
312     // Record which Symbol names have been dumped already.
313     private HashSet<Symbol> names;
314 
315     private static final long HPROF_SEGMENTED_HEAP_DUMP_THRESHOLD = 2L * 0x40000000;
316 
317     // The approximate size of a heap segment. Used to calculate when to create
318     // a new segment.
319     private static final long HPROF_SEGMENTED_HEAP_DUMP_SEGMENT_SIZE = 1L * 0x40000000;
320 
321     // hprof binary file header
322     private static final String HPROF_HEADER_1_0_2 = "JAVA PROFILE 1.0.2";
323 
324     // constants in enum HprofTag
325     private static final int HPROF_UTF8             = 0x01;
326     private static final int HPROF_LOAD_CLASS       = 0x02;
327     private static final int HPROF_UNLOAD_CLASS     = 0x03;
328     private static final int HPROF_FRAME            = 0x04;
329     private static final int HPROF_TRACE            = 0x05;
330     private static final int HPROF_ALLOC_SITES      = 0x06;
331     private static final int HPROF_HEAP_SUMMARY     = 0x07;
332     private static final int HPROF_START_THREAD     = 0x0A;
333     private static final int HPROF_END_THREAD       = 0x0B;
334     private static final int HPROF_HEAP_DUMP        = 0x0C;
335     private static final int HPROF_CPU_SAMPLES      = 0x0D;
336     private static final int HPROF_CONTROL_SETTINGS = 0x0E;
337 
338     // 1.0.2 record types
339     private static final int HPROF_HEAP_DUMP_SEGMENT = 0x1C;
340     private static final int HPROF_HEAP_DUMP_END     = 0x2C;
341 
342     // Heap dump constants
343     // constants in enum HprofGcTag
344     private static final int HPROF_GC_ROOT_UNKNOWN       = 0xFF;
345     private static final int HPROF_GC_ROOT_JNI_GLOBAL    = 0x01;
346     private static final int HPROF_GC_ROOT_JNI_LOCAL     = 0x02;
347     private static final int HPROF_GC_ROOT_JAVA_FRAME    = 0x03;
348     private static final int HPROF_GC_ROOT_NATIVE_STACK  = 0x04;
349     private static final int HPROF_GC_ROOT_STICKY_CLASS  = 0x05;
350     private static final int HPROF_GC_ROOT_THREAD_BLOCK  = 0x06;
351     private static final int HPROF_GC_ROOT_MONITOR_USED  = 0x07;
352     private static final int HPROF_GC_ROOT_THREAD_OBJ    = 0x08;
353     private static final int HPROF_GC_CLASS_DUMP         = 0x20;
354     private static final int HPROF_GC_INSTANCE_DUMP      = 0x21;
355     private static final int HPROF_GC_OBJ_ARRAY_DUMP     = 0x22;
356     private static final int HPROF_GC_PRIM_ARRAY_DUMP    = 0x23;
357 
358     // constants in enum HprofType
359     private static final int HPROF_ARRAY_OBJECT  = 1;
360     private static final int HPROF_NORMAL_OBJECT = 2;
361     private static final int HPROF_BOOLEAN       = 4;
362     private static final int HPROF_CHAR          = 5;
363     private static final int HPROF_FLOAT         = 6;
364     private static final int HPROF_DOUBLE        = 7;
365     private static final int HPROF_BYTE          = 8;
366     private static final int HPROF_SHORT         = 9;
367     private static final int HPROF_INT           = 10;
368     private static final int HPROF_LONG          = 11;
369 
370     // Java type codes
371     private static final int JVM_SIGNATURE_BOOLEAN = 'Z';
372     private static final int JVM_SIGNATURE_CHAR    = 'C';
373     private static final int JVM_SIGNATURE_BYTE    = 'B';
374     private static final int JVM_SIGNATURE_SHORT   = 'S';
375     private static final int JVM_SIGNATURE_INT     = 'I';
376     private static final int JVM_SIGNATURE_LONG    = 'J';
377     private static final int JVM_SIGNATURE_FLOAT   = 'F';
378     private static final int JVM_SIGNATURE_DOUBLE  = 'D';
379     private static final int JVM_SIGNATURE_ARRAY   = '[';
380     private static final int JVM_SIGNATURE_CLASS   = 'L';
381 
382     private static final long MAX_U4_VALUE = 0xFFFFFFFFL;
383     int serialNum = 1;
384 
HeapHprofBinWriter()385     public HeapHprofBinWriter() {
386         this.KlassMap = new ArrayList<Klass>();
387         this.names = new HashSet<Symbol>();
388     }
389 
write(String fileName)390     public synchronized void write(String fileName) throws IOException {
391         // open file stream and create buffered data output stream
392         fos = new FileOutputStream(fileName);
393         out = new DataOutputStream(new BufferedOutputStream(fos));
394 
395         VM vm = VM.getVM();
396         dbg = vm.getDebugger();
397         objectHeap = vm.getObjectHeap();
398 
399         OBJ_ID_SIZE = (int) vm.getOopSize();
400 
401         BOOLEAN_BASE_OFFSET = TypeArray.baseOffsetInBytes(BasicType.T_BOOLEAN);
402         BYTE_BASE_OFFSET = TypeArray.baseOffsetInBytes(BasicType.T_BYTE);
403         CHAR_BASE_OFFSET = TypeArray.baseOffsetInBytes(BasicType.T_CHAR);
404         SHORT_BASE_OFFSET = TypeArray.baseOffsetInBytes(BasicType.T_SHORT);
405         INT_BASE_OFFSET = TypeArray.baseOffsetInBytes(BasicType.T_INT);
406         LONG_BASE_OFFSET = TypeArray.baseOffsetInBytes(BasicType.T_LONG);
407         FLOAT_BASE_OFFSET = TypeArray.baseOffsetInBytes(BasicType.T_FLOAT);
408         DOUBLE_BASE_OFFSET = TypeArray.baseOffsetInBytes(BasicType.T_DOUBLE);
409         OBJECT_BASE_OFFSET = TypeArray.baseOffsetInBytes(BasicType.T_OBJECT);
410 
411         BOOLEAN_SIZE = objectHeap.getBooleanSize();
412         BYTE_SIZE = objectHeap.getByteSize();
413         CHAR_SIZE = objectHeap.getCharSize();
414         SHORT_SIZE = objectHeap.getShortSize();
415         INT_SIZE = objectHeap.getIntSize();
416         LONG_SIZE = objectHeap.getLongSize();
417         FLOAT_SIZE = objectHeap.getFloatSize();
418         DOUBLE_SIZE = objectHeap.getDoubleSize();
419 
420         // Check weather we should dump the heap as segments
421         useSegmentedHeapDump = vm.getUniverse().heap().used() > HPROF_SEGMENTED_HEAP_DUMP_THRESHOLD;
422 
423         // hprof bin format header
424         writeFileHeader();
425 
426         // dummy stack trace without any frames so that
427         // HAT can be run without -stack false option
428         writeDummyTrace();
429 
430         // hprof UTF-8 symbols section
431         writeSymbols();
432 
433         // HPROF_LOAD_CLASS records for all classes
434         writeClasses();
435 
436         // write HPROF_FRAME and HPROF_TRACE records
437         dumpStackTraces();
438 
439         // write CLASS_DUMP records
440         writeClassDumpRecords();
441 
442         // this will write heap data into the buffer stream
443         super.write();
444 
445         // flush buffer stream.
446         out.flush();
447 
448         // Fill in final length
449         fillInHeapRecordLength();
450 
451         if (useSegmentedHeapDump) {
452             // Write heap segment-end record
453             out.writeByte((byte) HPROF_HEAP_DUMP_END);
454             out.writeInt(0);
455             out.writeInt(0);
456         }
457 
458         // flush buffer stream and throw it.
459         out.flush();
460         out = null;
461 
462         // close the file stream
463         fos.close();
464     }
465 
466     @Override
writeHeapRecordPrologue()467     protected void writeHeapRecordPrologue() throws IOException {
468         if (currentSegmentStart == 0) {
469             // write heap data header, depending on heap size use segmented heap
470             // format
471             out.writeByte((byte) (useSegmentedHeapDump ? HPROF_HEAP_DUMP_SEGMENT
472                     : HPROF_HEAP_DUMP));
473             out.writeInt(0);
474 
475             // remember position of dump length, we will fixup
476             // length later - hprof format requires length.
477             out.flush();
478             currentSegmentStart = fos.getChannel().position();
479             // write dummy length of 0 and we'll fix it later.
480             out.writeInt(0);
481         }
482     }
483 
484     @Override
writeHeapRecordEpilogue()485     protected void writeHeapRecordEpilogue() throws IOException {
486         if (useSegmentedHeapDump) {
487             out.flush();
488             if ((fos.getChannel().position() - currentSegmentStart - 4L) >= HPROF_SEGMENTED_HEAP_DUMP_SEGMENT_SIZE) {
489                 fillInHeapRecordLength();
490                 currentSegmentStart = 0;
491             }
492         }
493     }
494 
fillInHeapRecordLength()495     private void fillInHeapRecordLength() throws IOException {
496 
497         // now get the current position to calculate length
498         long dumpEnd = fos.getChannel().position();
499 
500         // calculate the length of heap data
501         long dumpLenLong = (dumpEnd - currentSegmentStart - 4L);
502 
503         // Check length boundary, overflow could happen but is _very_ unlikely
504         if (dumpLenLong >= (4L * 0x40000000)) {
505             throw new RuntimeException("Heap segment size overflow.");
506         }
507 
508         // Save the current position
509         long currentPosition = fos.getChannel().position();
510 
511         // seek the position to write length
512         fos.getChannel().position(currentSegmentStart);
513 
514         int dumpLen = (int) dumpLenLong;
515 
516         // write length as integer
517         fos.write((dumpLen >>> 24) & 0xFF);
518         fos.write((dumpLen >>> 16) & 0xFF);
519         fos.write((dumpLen >>> 8) & 0xFF);
520         fos.write((dumpLen >>> 0) & 0xFF);
521 
522         //Reset to previous current position
523         fos.getChannel().position(currentPosition);
524     }
525 
526     // get the size in bytes for the requested type
getSizeForType(int type)527     private long getSizeForType(int type) throws IOException {
528         switch (type) {
529             case TypeArrayKlass.T_BOOLEAN:
530                 return BOOLEAN_SIZE;
531             case TypeArrayKlass.T_INT:
532                 return INT_SIZE;
533             case TypeArrayKlass.T_CHAR:
534                 return CHAR_SIZE;
535             case TypeArrayKlass.T_SHORT:
536                 return SHORT_SIZE;
537             case TypeArrayKlass.T_BYTE:
538                 return BYTE_SIZE;
539             case TypeArrayKlass.T_LONG:
540                 return LONG_SIZE;
541             case TypeArrayKlass.T_FLOAT:
542                 return FLOAT_SIZE;
543             case TypeArrayKlass.T_DOUBLE:
544                 return DOUBLE_SIZE;
545             default:
546                 throw new RuntimeException(
547                     "Should not reach here: Unknown type: " + type);
548          }
549     }
550 
getArrayHeaderSize(boolean isObjectAarray)551     private int getArrayHeaderSize(boolean isObjectAarray) {
552         return isObjectAarray?
553             ((int) BYTE_SIZE + 2 * (int) INT_SIZE + 2 * (int) OBJ_ID_SIZE):
554             (2 * (int) BYTE_SIZE + 2 * (int) INT_SIZE + (int) OBJ_ID_SIZE);
555     }
556 
557     // Check if we need to truncate an array
calculateArrayMaxLength(long originalArrayLength, int headerSize, long typeSize, String typeName)558     private int calculateArrayMaxLength(long originalArrayLength,
559                                         int headerSize,
560                                         long typeSize,
561                                         String typeName) throws IOException {
562 
563         long length = originalArrayLength;
564 
565         // now get the current position to calculate length
566         long dumpEnd = fos.getChannel().position();
567         long originalLengthInBytes = originalArrayLength * typeSize;
568 
569         // calculate the length of heap data
570         long currentRecordLength = (dumpEnd - currentSegmentStart - 4L);
571         if (currentRecordLength > 0 &&
572             (currentRecordLength + headerSize + originalLengthInBytes) > MAX_U4_VALUE) {
573             fillInHeapRecordLength();
574             currentSegmentStart = 0;
575             writeHeapRecordPrologue();
576             currentRecordLength = 0;
577         }
578 
579         // Calculate the max bytes we can use.
580         long maxBytes = (MAX_U4_VALUE - (headerSize + currentRecordLength));
581 
582         if (originalLengthInBytes > maxBytes) {
583             length = maxBytes/typeSize;
584             System.err.println("WARNING: Cannot dump array of type " + typeName
585                                + " with length " + originalArrayLength
586                                + "; truncating to length " + length);
587         }
588         return (int) length;
589     }
590 
writeClassDumpRecords()591     private void writeClassDumpRecords() throws IOException {
592         ClassLoaderDataGraph cldGraph = VM.getVM().getClassLoaderDataGraph();
593         try {
594              cldGraph.classesDo(new ClassLoaderDataGraph.ClassVisitor() {
595                             public void visit(Klass k) {
596                                 try {
597                                     writeHeapRecordPrologue();
598                                     writeClassDumpRecord(k);
599                                     writeHeapRecordEpilogue();
600                                 } catch (IOException e) {
601                                     throw new RuntimeException(e);
602                                 }
603                             }
604                         });
605         } catch (RuntimeException re) {
606             handleRuntimeException(re);
607         }
608     }
609 
writeClass(Instance instance)610     protected void writeClass(Instance instance) throws IOException {
611         Klass reflectedKlass = java_lang_Class.asKlass(instance);
612         // dump instance record only for primitive type Class objects.
613         // all other Class objects are covered by writeClassDumpRecords.
614         if (reflectedKlass == null) {
615             writeInstance(instance);
616         }
617     }
618 
writeClassDumpRecord(Klass k)619     private void writeClassDumpRecord(Klass k) throws IOException {
620         out.writeByte((byte)HPROF_GC_CLASS_DUMP);
621         writeObjectID(k.getJavaMirror());
622         out.writeInt(DUMMY_STACK_TRACE_ID);
623         Klass superKlass = k.getJavaSuper();
624         if (superKlass != null) {
625             writeObjectID(superKlass.getJavaMirror());
626         } else {
627             writeObjectID(null);
628         }
629 
630         if (k instanceof InstanceKlass) {
631             InstanceKlass ik = (InstanceKlass) k;
632             writeObjectID(ik.getClassLoader());
633             writeObjectID(null);  // ik.getJavaMirror().getSigners());
634             writeObjectID(null);  // ik.getJavaMirror().getProtectionDomain());
635             // two reserved id fields
636             writeObjectID(null);
637             writeObjectID(null);
638             List fields = getInstanceFields(ik);
639             int instSize = getSizeForFields(fields);
640             classDataCache.put(ik, new ClassData(instSize, fields));
641             out.writeInt(instSize);
642 
643             // For now, ignore constant pool - HAT ignores too!
644             // output number of cp entries as zero.
645             out.writeShort((short) 0);
646 
647             List declaredFields = ik.getImmediateFields();
648             List staticFields = new ArrayList();
649             List instanceFields = new ArrayList();
650             Iterator itr = null;
651             for (itr = declaredFields.iterator(); itr.hasNext();) {
652                 Field field = (Field) itr.next();
653                 if (field.isStatic()) {
654                     staticFields.add(field);
655                 } else {
656                     instanceFields.add(field);
657                 }
658             }
659 
660             // dump static field descriptors
661             writeFieldDescriptors(staticFields, ik);
662 
663             // dump instance field descriptors
664             writeFieldDescriptors(instanceFields, null);
665         } else {
666             if (k instanceof ObjArrayKlass) {
667                 ObjArrayKlass oak = (ObjArrayKlass) k;
668                 Klass bottomKlass = oak.getBottomKlass();
669                 if (bottomKlass instanceof InstanceKlass) {
670                     InstanceKlass ik = (InstanceKlass) bottomKlass;
671                     writeObjectID(ik.getClassLoader());
672                     writeObjectID(null); // ik.getJavaMirror().getSigners());
673                     writeObjectID(null); // ik.getJavaMirror().getProtectionDomain());
674                 } else {
675                     writeObjectID(null);
676                     writeObjectID(null);
677                     writeObjectID(null);
678                 }
679             } else {
680                 writeObjectID(null);
681                 writeObjectID(null);
682                 writeObjectID(null);
683             }
684             // two reserved id fields
685             writeObjectID(null);
686             writeObjectID(null);
687             // write zero instance size -- as instance size
688             // is variable for arrays.
689             out.writeInt(0);
690             // no constant pool for array klasses
691             out.writeShort((short) 0);
692             // no static fields for array klasses
693             out.writeShort((short) 0);
694             // no instance fields for array klasses
695             out.writeShort((short) 0);
696         }
697     }
698 
dumpStackTraces()699     private void dumpStackTraces() throws IOException {
700         // write a HPROF_TRACE record without any frames to be referenced as object alloc sites
701         writeHeader(HPROF_TRACE, 3 * (int)INT_SIZE );
702         out.writeInt(DUMMY_STACK_TRACE_ID);
703         out.writeInt(0);                    // thread number
704         out.writeInt(0);                    // frame count
705 
706         int frameSerialNum = 0;
707         int numThreads = 0;
708         Threads threads = VM.getVM().getThreads();
709 
710         for (JavaThread thread = threads.first(); thread != null; thread = thread.next()) {
711             Oop threadObj = thread.getThreadObj();
712             if (threadObj != null && !thread.isExiting() && !thread.isHiddenFromExternalView()) {
713 
714                 // dump thread stack trace
715                 ThreadStackTrace st = new ThreadStackTrace(thread);
716                 st.dumpStack(-1);
717                 numThreads++;
718 
719                 // write HPROF_FRAME records for this thread's stack trace
720                 int depth = st.getStackDepth();
721                 int threadFrameStart = frameSerialNum;
722                 for (int j=0; j < depth; j++) {
723                     StackFrameInfo frame = st.stackFrameAt(j);
724                     Method m = frame.getMethod();
725                     int classSerialNum = KlassMap.indexOf(m.getMethodHolder()) + 1;
726                     // the class serial number starts from 1
727                     assert classSerialNum > 0:"class not found";
728                     dumpStackFrame(++frameSerialNum, classSerialNum, m, frame.getBCI());
729                 }
730 
731                 // write HPROF_TRACE record for one thread
732                 writeHeader(HPROF_TRACE, 3 * (int)INT_SIZE + depth * (int)VM.getVM().getOopSize());
733                 int stackSerialNum = numThreads + DUMMY_STACK_TRACE_ID;
734                 out.writeInt(stackSerialNum);      // stack trace serial number
735                 out.writeInt(numThreads);          // thread serial number
736                 out.writeInt(depth);               // frame count
737                 for (int j=1; j <= depth; j++) {
738                     writeObjectID(threadFrameStart + j);
739                 }
740             }
741         }
742     }
743 
dumpStackFrame(int frameSN, int classSN, Method m, int bci)744     private void dumpStackFrame(int frameSN, int classSN, Method m, int bci) throws IOException {
745         int lineNumber;
746         if (m.isNative()) {
747             lineNumber = -3; // native frame
748         } else {
749             lineNumber = m.getLineNumberFromBCI(bci);
750         }
751         // First dump UTF8 if needed
752         writeSymbol(m.getName());                              // method's name
753         writeSymbol(m.getSignature());                         // method's signature
754         writeSymbol(m.getMethodHolder().getSourceFileName());  // source file name
755         // Then write FRAME descriptor
756         writeHeader(HPROF_FRAME, 4 * (int)VM.getVM().getOopSize() + 2 * (int)INT_SIZE);
757         writeObjectID(frameSN);                                  // frame serial number
758         writeSymbolID(m.getName());                              // method's name
759         writeSymbolID(m.getSignature());                         // method's signature
760         writeSymbolID(m.getMethodHolder().getSourceFileName());  // source file name
761         out.writeInt(classSN);                                   // class serial number
762         out.writeInt(lineNumber);                                // line number
763     }
764 
writeJavaThread(JavaThread jt, int index)765     protected void writeJavaThread(JavaThread jt, int index) throws IOException {
766         out.writeByte((byte) HPROF_GC_ROOT_THREAD_OBJ);
767         writeObjectID(jt.getThreadObj());
768         out.writeInt(index);
769         out.writeInt(DUMMY_STACK_TRACE_ID);
770         writeLocalJNIHandles(jt, index);
771     }
772 
writeLocalJNIHandles(JavaThread jt, int index)773     protected void writeLocalJNIHandles(JavaThread jt, int index) throws IOException {
774         final int threadIndex = index;
775         JNIHandleBlock blk = jt.activeHandles();
776         if (blk != null) {
777             try {
778                 blk.oopsDo(new AddressVisitor() {
779                            public void visitAddress(Address handleAddr) {
780                                try {
781                                    if (handleAddr != null) {
782                                        OopHandle oopHandle = handleAddr.getOopHandleAt(0);
783                                        Oop oop = objectHeap.newOop(oopHandle);
784                                        // exclude JNI handles hotspot internal objects
785                                        if (oop != null && isJavaVisible(oop)) {
786                                            out.writeByte((byte) HPROF_GC_ROOT_JNI_LOCAL);
787                                            writeObjectID(oop);
788                                            out.writeInt(threadIndex);
789                                            out.writeInt(EMPTY_FRAME_DEPTH);
790                                        }
791                                    }
792                                } catch (IOException exp) {
793                                    throw new RuntimeException(exp);
794                                }
795                            }
796                            public void visitCompOopAddress(Address handleAddr) {
797                              throw new RuntimeException(
798                                    " Should not reach here. JNIHandles are not compressed \n");
799                            }
800                        });
801             } catch (RuntimeException re) {
802                 handleRuntimeException(re);
803             }
804         }
805     }
806 
writeGlobalJNIHandle(Address handleAddr)807     protected void writeGlobalJNIHandle(Address handleAddr) throws IOException {
808         OopHandle oopHandle = handleAddr.getOopHandleAt(0);
809         Oop oop = objectHeap.newOop(oopHandle);
810         // exclude JNI handles of hotspot internal objects
811         if (oop != null && isJavaVisible(oop)) {
812             out.writeByte((byte) HPROF_GC_ROOT_JNI_GLOBAL);
813             writeObjectID(oop);
814             // use JNIHandle address as ID
815             writeObjectID(getAddressValue(handleAddr));
816         }
817     }
818 
writeObjectArray(ObjArray array)819     protected void writeObjectArray(ObjArray array) throws IOException {
820         int headerSize = getArrayHeaderSize(true);
821         final int length = calculateArrayMaxLength(array.getLength(),
822                                                    headerSize,
823                                                    OBJ_ID_SIZE,
824                                                    "Object");
825         out.writeByte((byte) HPROF_GC_OBJ_ARRAY_DUMP);
826         writeObjectID(array);
827         out.writeInt(DUMMY_STACK_TRACE_ID);
828         out.writeInt(length);
829         writeObjectID(array.getKlass().getJavaMirror());
830         for (int index = 0; index < length; index++) {
831             OopHandle handle = array.getOopHandleAt(index);
832             writeObjectID(getAddressValue(handle));
833         }
834     }
835 
writePrimitiveArray(TypeArray array)836     protected void writePrimitiveArray(TypeArray array) throws IOException {
837         int headerSize = getArrayHeaderSize(false);
838         TypeArrayKlass tak = (TypeArrayKlass) array.getKlass();
839         final int type = (int) tak.getElementType();
840         final String typeName = tak.getElementTypeName();
841         final long typeSize = getSizeForType(type);
842         final int length = calculateArrayMaxLength(array.getLength(),
843                                                    headerSize,
844                                                    typeSize,
845                                                    typeName);
846         out.writeByte((byte) HPROF_GC_PRIM_ARRAY_DUMP);
847         writeObjectID(array);
848         out.writeInt(DUMMY_STACK_TRACE_ID);
849         out.writeInt(length);
850         out.writeByte((byte) type);
851         switch (type) {
852             case TypeArrayKlass.T_BOOLEAN:
853                 writeBooleanArray(array, length);
854                 break;
855             case TypeArrayKlass.T_CHAR:
856                 writeCharArray(array, length);
857                 break;
858             case TypeArrayKlass.T_FLOAT:
859                 writeFloatArray(array, length);
860                 break;
861             case TypeArrayKlass.T_DOUBLE:
862                 writeDoubleArray(array, length);
863                 break;
864             case TypeArrayKlass.T_BYTE:
865                 writeByteArray(array, length);
866                 break;
867             case TypeArrayKlass.T_SHORT:
868                 writeShortArray(array, length);
869                 break;
870             case TypeArrayKlass.T_INT:
871                 writeIntArray(array, length);
872                 break;
873             case TypeArrayKlass.T_LONG:
874                 writeLongArray(array, length);
875                 break;
876             default:
877                 throw new RuntimeException(
878                     "Should not reach here: Unknown type: " + type);
879         }
880     }
881 
writeBooleanArray(TypeArray array, int length)882     private void writeBooleanArray(TypeArray array, int length) throws IOException {
883         for (int index = 0; index < length; index++) {
884              long offset = BOOLEAN_BASE_OFFSET + index * BOOLEAN_SIZE;
885              out.writeBoolean(array.getHandle().getJBooleanAt(offset));
886         }
887     }
888 
writeByteArray(TypeArray array, int length)889     private void writeByteArray(TypeArray array, int length) throws IOException {
890         for (int index = 0; index < length; index++) {
891              long offset = BYTE_BASE_OFFSET + index * BYTE_SIZE;
892              out.writeByte(array.getHandle().getJByteAt(offset));
893         }
894     }
895 
writeShortArray(TypeArray array, int length)896     private void writeShortArray(TypeArray array, int length) throws IOException {
897         for (int index = 0; index < length; index++) {
898              long offset = SHORT_BASE_OFFSET + index * SHORT_SIZE;
899              out.writeShort(array.getHandle().getJShortAt(offset));
900         }
901     }
902 
writeIntArray(TypeArray array, int length)903     private void writeIntArray(TypeArray array, int length) throws IOException {
904         for (int index = 0; index < length; index++) {
905              long offset = INT_BASE_OFFSET + index * INT_SIZE;
906              out.writeInt(array.getHandle().getJIntAt(offset));
907         }
908     }
909 
writeLongArray(TypeArray array, int length)910     private void writeLongArray(TypeArray array, int length) throws IOException {
911         for (int index = 0; index < length; index++) {
912              long offset = LONG_BASE_OFFSET + index * LONG_SIZE;
913              out.writeLong(array.getHandle().getJLongAt(offset));
914         }
915     }
916 
writeCharArray(TypeArray array, int length)917     private void writeCharArray(TypeArray array, int length) throws IOException {
918         for (int index = 0; index < length; index++) {
919              long offset = CHAR_BASE_OFFSET + index * CHAR_SIZE;
920              out.writeChar(array.getHandle().getJCharAt(offset));
921         }
922     }
923 
writeFloatArray(TypeArray array, int length)924     private void writeFloatArray(TypeArray array, int length) throws IOException {
925         for (int index = 0; index < length; index++) {
926              long offset = FLOAT_BASE_OFFSET + index * FLOAT_SIZE;
927              out.writeFloat(array.getHandle().getJFloatAt(offset));
928         }
929     }
930 
writeDoubleArray(TypeArray array, int length)931     private void writeDoubleArray(TypeArray array, int length) throws IOException {
932         for (int index = 0; index < length; index++) {
933              long offset = DOUBLE_BASE_OFFSET + index * DOUBLE_SIZE;
934              out.writeDouble(array.getHandle().getJDoubleAt(offset));
935         }
936     }
937 
writeInstance(Instance instance)938     protected void writeInstance(Instance instance) throws IOException {
939         out.writeByte((byte) HPROF_GC_INSTANCE_DUMP);
940         writeObjectID(instance);
941         out.writeInt(DUMMY_STACK_TRACE_ID);
942         Klass klass = instance.getKlass();
943         writeObjectID(klass.getJavaMirror());
944 
945         ClassData cd = (ClassData) classDataCache.get(klass);
946 
947         if (Assert.ASSERTS_ENABLED) {
948             Assert.that(cd != null, "can not get class data for " + klass.getName().asString() + klass.getAddress());
949         }
950         List fields = cd.fields;
951         int size = cd.instSize;
952         out.writeInt(size);
953         for (Iterator itr = fields.iterator(); itr.hasNext();) {
954             writeField((Field) itr.next(), instance);
955         }
956     }
957 
958     //-- Internals only below this point
959 
writeFieldDescriptors(List fields, InstanceKlass ik)960     private void writeFieldDescriptors(List fields, InstanceKlass ik)
961         throws IOException {
962         // ik == null for instance fields.
963         out.writeShort((short) fields.size());
964         for (Iterator itr = fields.iterator(); itr.hasNext();) {
965             Field field = (Field) itr.next();
966             Symbol name = field.getName();
967             writeSymbolID(name);
968             char typeCode = (char) field.getSignature().getByteAt(0);
969             int kind = signatureToHprofKind(typeCode);
970             out.writeByte((byte)kind);
971             if (ik != null) {
972                 // static field
973                 writeField(field, ik.getJavaMirror());
974             }
975         }
976     }
977 
signatureToHprofKind(char ch)978     public static int signatureToHprofKind(char ch) {
979         switch (ch) {
980         case JVM_SIGNATURE_CLASS:
981         case JVM_SIGNATURE_ARRAY:
982             return HPROF_NORMAL_OBJECT;
983         case JVM_SIGNATURE_BOOLEAN:
984             return HPROF_BOOLEAN;
985         case JVM_SIGNATURE_CHAR:
986             return HPROF_CHAR;
987         case JVM_SIGNATURE_FLOAT:
988             return HPROF_FLOAT;
989         case JVM_SIGNATURE_DOUBLE:
990             return HPROF_DOUBLE;
991         case JVM_SIGNATURE_BYTE:
992             return HPROF_BYTE;
993         case JVM_SIGNATURE_SHORT:
994             return HPROF_SHORT;
995         case JVM_SIGNATURE_INT:
996             return HPROF_INT;
997         case JVM_SIGNATURE_LONG:
998             return HPROF_LONG;
999         default:
1000             throw new RuntimeException("should not reach here");
1001         }
1002     }
1003 
writeField(Field field, Oop oop)1004     private void writeField(Field field, Oop oop) throws IOException {
1005         char typeCode = (char) field.getSignature().getByteAt(0);
1006         switch (typeCode) {
1007         case JVM_SIGNATURE_BOOLEAN:
1008             out.writeBoolean(((BooleanField)field).getValue(oop));
1009             break;
1010         case JVM_SIGNATURE_CHAR:
1011             out.writeChar(((CharField)field).getValue(oop));
1012             break;
1013         case JVM_SIGNATURE_BYTE:
1014             out.writeByte(((ByteField)field).getValue(oop));
1015             break;
1016         case JVM_SIGNATURE_SHORT:
1017             out.writeShort(((ShortField)field).getValue(oop));
1018             break;
1019         case JVM_SIGNATURE_INT:
1020             out.writeInt(((IntField)field).getValue(oop));
1021             break;
1022         case JVM_SIGNATURE_LONG:
1023             out.writeLong(((LongField)field).getValue(oop));
1024             break;
1025         case JVM_SIGNATURE_FLOAT:
1026             out.writeFloat(((FloatField)field).getValue(oop));
1027             break;
1028         case JVM_SIGNATURE_DOUBLE:
1029             out.writeDouble(((DoubleField)field).getValue(oop));
1030             break;
1031         case JVM_SIGNATURE_CLASS:
1032         case JVM_SIGNATURE_ARRAY: {
1033             if (VM.getVM().isCompressedOopsEnabled()) {
1034               OopHandle handle = ((NarrowOopField)field).getValueAsOopHandle(oop);
1035               writeObjectID(getAddressValue(handle));
1036             } else {
1037               OopHandle handle = ((OopField)field).getValueAsOopHandle(oop);
1038               writeObjectID(getAddressValue(handle));
1039             }
1040             break;
1041         }
1042         default:
1043             throw new RuntimeException("should not reach here");
1044         }
1045     }
1046 
writeHeader(int tag, int len)1047     private void writeHeader(int tag, int len) throws IOException {
1048         out.writeByte((byte)tag);
1049         out.writeInt(0); // current ticks
1050         out.writeInt(len);
1051     }
1052 
writeDummyTrace()1053     private void writeDummyTrace() throws IOException {
1054         writeHeader(HPROF_TRACE, 3 * 4);
1055         out.writeInt(DUMMY_STACK_TRACE_ID);
1056         out.writeInt(0);
1057         out.writeInt(0);
1058     }
1059 
writeClassSymbols(Klass k)1060     private void writeClassSymbols(Klass k) throws IOException {
1061         writeSymbol(k.getName());
1062         if (k instanceof InstanceKlass) {
1063             InstanceKlass ik = (InstanceKlass) k;
1064             List declaredFields = ik.getImmediateFields();
1065             for (Iterator itr = declaredFields.iterator(); itr.hasNext();) {
1066                 Field field = (Field) itr.next();
1067                 writeSymbol(field.getName());
1068             }
1069         }
1070     }
1071 
writeSymbols()1072     private void writeSymbols() throws IOException {
1073         // Write all the symbols that are used by the classes
1074         ClassLoaderDataGraph cldGraph = VM.getVM().getClassLoaderDataGraph();
1075         try {
1076              cldGraph.classesDo(new ClassLoaderDataGraph.ClassVisitor() {
1077                             public void visit(Klass k) {
1078                                 try {
1079                                     writeClassSymbols(k);
1080                                 } catch (IOException e) {
1081                                     throw new RuntimeException(e);
1082                                 }
1083                             }
1084                         });
1085         } catch (RuntimeException re) {
1086             handleRuntimeException(re);
1087         }
1088     }
1089 
writeSymbol(Symbol sym)1090     private void writeSymbol(Symbol sym) throws IOException {
1091         if(sym != null) {
1092             // If name is already written don't write it again.
1093             if (names.add(sym)) {
1094                 byte[] buf = sym.asString().getBytes("UTF-8");
1095                 writeHeader(HPROF_UTF8, buf.length + OBJ_ID_SIZE);
1096                 writeSymbolID(sym);
1097                 out.write(buf);
1098             }
1099         } else {
1100             writeHeader(HPROF_UTF8, 0 + OBJ_ID_SIZE);
1101             writeSymbolID(null);
1102         }
1103     }
1104 
writeClasses()1105     private void writeClasses() throws IOException {
1106         // write class list (id, name) association
1107         ClassLoaderDataGraph cldGraph = VM.getVM().getClassLoaderDataGraph();
1108         try {
1109             cldGraph.classesDo(new ClassLoaderDataGraph.ClassVisitor() {
1110                 public void visit(Klass k) {
1111                     try {
1112                         Instance clazz = k.getJavaMirror();
1113                         writeHeader(HPROF_LOAD_CLASS, 2 * (OBJ_ID_SIZE + 4));
1114                         out.writeInt(serialNum);
1115                         writeObjectID(clazz);
1116                         KlassMap.add(serialNum - 1, k);
1117                         out.writeInt(DUMMY_STACK_TRACE_ID);
1118                         writeSymbolID(k.getName());
1119                         serialNum++;
1120                     } catch (IOException exp) {
1121                         throw new RuntimeException(exp);
1122                     }
1123                 }
1124             });
1125         } catch (RuntimeException re) {
1126             handleRuntimeException(re);
1127         }
1128     }
1129 
1130     // writes hprof binary file header
writeFileHeader()1131     private void writeFileHeader() throws IOException {
1132         // version string
1133         out.writeBytes(HPROF_HEADER_1_0_2);
1134         out.writeByte((byte)'\0');
1135 
1136         // write identifier size. we use pointers as identifiers.
1137         out.writeInt(OBJ_ID_SIZE);
1138 
1139         // timestamp -- file creation time.
1140         out.writeLong(System.currentTimeMillis());
1141     }
1142 
1143     // writes unique ID for an object
writeObjectID(Oop oop)1144     private void writeObjectID(Oop oop) throws IOException {
1145         OopHandle handle = (oop != null)? oop.getHandle() : null;
1146         long address = getAddressValue(handle);
1147         writeObjectID(address);
1148     }
1149 
writeSymbolID(Symbol sym)1150     private void writeSymbolID(Symbol sym) throws IOException {
1151         assert (sym == null || names.contains(sym));
1152         long address = (sym != null) ? getAddressValue(sym.getAddress()) : getAddressValue(null);
1153         writeObjectID(address);
1154     }
1155 
writeObjectID(long address)1156     private void writeObjectID(long address) throws IOException {
1157         if (OBJ_ID_SIZE == 4) {
1158             out.writeInt((int) address);
1159         } else {
1160             out.writeLong(address);
1161         }
1162     }
1163 
getAddressValue(Address addr)1164     private long getAddressValue(Address addr) {
1165         return (addr == null)? 0L : dbg.getAddressValue(addr);
1166     }
1167 
1168     // get all declared as well as inherited (directly/indirectly) fields
getInstanceFields(InstanceKlass ik)1169     private static List/*<Field>*/ getInstanceFields(InstanceKlass ik) {
1170         InstanceKlass klass = ik;
1171         List res = new ArrayList();
1172         while (klass != null) {
1173             List curFields = klass.getImmediateFields();
1174             for (Iterator itr = curFields.iterator(); itr.hasNext();) {
1175                 Field f = (Field) itr.next();
1176                 if (! f.isStatic()) {
1177                     res.add(f);
1178                 }
1179             }
1180             klass = (InstanceKlass) klass.getSuper();
1181         }
1182         return res;
1183     }
1184 
1185     // get size in bytes (in stream) required for given fields.  Note
1186     // that this is not the same as object size in heap. The size in
1187     // heap will include size of padding/alignment bytes as well.
getSizeForFields(List fields)1188     private int getSizeForFields(List fields) {
1189         int size = 0;
1190         for (Iterator itr = fields.iterator(); itr.hasNext();) {
1191             Field field = (Field) itr.next();
1192             char typeCode = (char) field.getSignature().getByteAt(0);
1193             switch (typeCode) {
1194             case JVM_SIGNATURE_BOOLEAN:
1195             case JVM_SIGNATURE_BYTE:
1196                 size++;
1197                 break;
1198             case JVM_SIGNATURE_CHAR:
1199             case JVM_SIGNATURE_SHORT:
1200                 size += 2;
1201                 break;
1202             case JVM_SIGNATURE_INT:
1203             case JVM_SIGNATURE_FLOAT:
1204                 size += 4;
1205                 break;
1206             case JVM_SIGNATURE_CLASS:
1207             case JVM_SIGNATURE_ARRAY:
1208                 size += OBJ_ID_SIZE;
1209                 break;
1210             case JVM_SIGNATURE_LONG:
1211             case JVM_SIGNATURE_DOUBLE:
1212                 size += 8;
1213                 break;
1214             default:
1215                 throw new RuntimeException("should not reach here");
1216             }
1217         }
1218         return size;
1219     }
1220 
1221     // We don't have allocation site info. We write a dummy
1222     // stack trace with this id.
1223     private static final int DUMMY_STACK_TRACE_ID = 1;
1224     private static final int EMPTY_FRAME_DEPTH = -1;
1225 
1226     private DataOutputStream out;
1227     private FileOutputStream fos;
1228     private Debugger dbg;
1229     private ObjectHeap objectHeap;
1230     private ArrayList<Klass> KlassMap;
1231 
1232     // oopSize of the debuggee
1233     private int OBJ_ID_SIZE;
1234 
1235     // Added for hprof file format 1.0.2 support
1236     private boolean useSegmentedHeapDump;
1237     private long currentSegmentStart;
1238 
1239     private long BOOLEAN_BASE_OFFSET;
1240     private long BYTE_BASE_OFFSET;
1241     private long CHAR_BASE_OFFSET;
1242     private long SHORT_BASE_OFFSET;
1243     private long INT_BASE_OFFSET;
1244     private long LONG_BASE_OFFSET;
1245     private long FLOAT_BASE_OFFSET;
1246     private long DOUBLE_BASE_OFFSET;
1247     private long OBJECT_BASE_OFFSET;
1248 
1249     private long BOOLEAN_SIZE;
1250     private long BYTE_SIZE;
1251     private long CHAR_SIZE;
1252     private long SHORT_SIZE;
1253     private long INT_SIZE;
1254     private long LONG_SIZE;
1255     private long FLOAT_SIZE;
1256     private long DOUBLE_SIZE;
1257 
1258     private static class ClassData {
1259         int instSize;
1260         List fields;
1261 
ClassData(int instSize, List fields)1262         ClassData(int instSize, List fields) {
1263             this.instSize = instSize;
1264             this.fields = fields;
1265         }
1266     }
1267 
1268     private Map classDataCache = new HashMap(); // <InstanceKlass, ClassData>
1269 }
1270