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 private static final long HPROF_SEGMENTED_HEAP_DUMP_THRESHOLD = 2L * 0x40000000;
313
314 // The approximate size of a heap segment. Used to calculate when to create
315 // a new segment.
316 private static final long HPROF_SEGMENTED_HEAP_DUMP_SEGMENT_SIZE = 1L * 0x40000000;
317
318 // hprof binary file header
319 private static final String HPROF_HEADER_1_0_2 = "JAVA PROFILE 1.0.2";
320
321 // constants in enum HprofTag
322 private static final int HPROF_UTF8 = 0x01;
323 private static final int HPROF_LOAD_CLASS = 0x02;
324 private static final int HPROF_UNLOAD_CLASS = 0x03;
325 private static final int HPROF_FRAME = 0x04;
326 private static final int HPROF_TRACE = 0x05;
327 private static final int HPROF_ALLOC_SITES = 0x06;
328 private static final int HPROF_HEAP_SUMMARY = 0x07;
329 private static final int HPROF_START_THREAD = 0x0A;
330 private static final int HPROF_END_THREAD = 0x0B;
331 private static final int HPROF_HEAP_DUMP = 0x0C;
364 private static final int HPROF_INT = 10;
365 private static final int HPROF_LONG = 11;
366
367 // Java type codes
368 private static final int JVM_SIGNATURE_BOOLEAN = 'Z';
369 private static final int JVM_SIGNATURE_CHAR = 'C';
370 private static final int JVM_SIGNATURE_BYTE = 'B';
371 private static final int JVM_SIGNATURE_SHORT = 'S';
372 private static final int JVM_SIGNATURE_INT = 'I';
373 private static final int JVM_SIGNATURE_LONG = 'J';
374 private static final int JVM_SIGNATURE_FLOAT = 'F';
375 private static final int JVM_SIGNATURE_DOUBLE = 'D';
376 private static final int JVM_SIGNATURE_ARRAY = '[';
377 private static final int JVM_SIGNATURE_CLASS = 'L';
378
379 private static final long MAX_U4_VALUE = 0xFFFFFFFFL;
380 int serialNum = 1;
381
382 public HeapHprofBinWriter() {
383 this.KlassMap = new ArrayList<Klass>();
384 }
385
386 public synchronized void write(String fileName) throws IOException {
387 // open file stream and create buffered data output stream
388 fos = new FileOutputStream(fileName);
389 out = new DataOutputStream(new BufferedOutputStream(fos));
390
391 VM vm = VM.getVM();
392 dbg = vm.getDebugger();
393 objectHeap = vm.getObjectHeap();
394 symTbl = vm.getSymbolTable();
395
396 OBJ_ID_SIZE = (int) vm.getOopSize();
397
398 BOOLEAN_BASE_OFFSET = TypeArray.baseOffsetInBytes(BasicType.T_BOOLEAN);
399 BYTE_BASE_OFFSET = TypeArray.baseOffsetInBytes(BasicType.T_BYTE);
400 CHAR_BASE_OFFSET = TypeArray.baseOffsetInBytes(BasicType.T_CHAR);
401 SHORT_BASE_OFFSET = TypeArray.baseOffsetInBytes(BasicType.T_SHORT);
402 INT_BASE_OFFSET = TypeArray.baseOffsetInBytes(BasicType.T_INT);
403 LONG_BASE_OFFSET = TypeArray.baseOffsetInBytes(BasicType.T_LONG);
404 FLOAT_BASE_OFFSET = TypeArray.baseOffsetInBytes(BasicType.T_FLOAT);
405 DOUBLE_BASE_OFFSET = TypeArray.baseOffsetInBytes(BasicType.T_DOUBLE);
406 OBJECT_BASE_OFFSET = TypeArray.baseOffsetInBytes(BasicType.T_OBJECT);
407
408 BOOLEAN_SIZE = objectHeap.getBooleanSize();
409 BYTE_SIZE = objectHeap.getByteSize();
410 CHAR_SIZE = objectHeap.getCharSize();
411 SHORT_SIZE = objectHeap.getShortSize();
412 INT_SIZE = objectHeap.getIntSize();
413 LONG_SIZE = objectHeap.getLongSize();
414 FLOAT_SIZE = objectHeap.getFloatSize();
728 // write HPROF_TRACE record for one thread
729 writeHeader(HPROF_TRACE, 3 * (int)INT_SIZE + depth * (int)VM.getVM().getOopSize());
730 int stackSerialNum = numThreads + DUMMY_STACK_TRACE_ID;
731 out.writeInt(stackSerialNum); // stack trace serial number
732 out.writeInt(numThreads); // thread serial number
733 out.writeInt(depth); // frame count
734 for (int j=1; j <= depth; j++) {
735 writeObjectID(threadFrameStart + j);
736 }
737 }
738 }
739 }
740
741 private void dumpStackFrame(int frameSN, int classSN, Method m, int bci) throws IOException {
742 int lineNumber;
743 if (m.isNative()) {
744 lineNumber = -3; // native frame
745 } else {
746 lineNumber = m.getLineNumberFromBCI(bci);
747 }
748 writeHeader(HPROF_FRAME, 4 * (int)VM.getVM().getOopSize() + 2 * (int)INT_SIZE);
749 writeObjectID(frameSN); // frame serial number
750 writeSymbolID(m.getName()); // method's name
751 writeSymbolID(m.getSignature()); // method's signature
752 writeSymbolID(m.getMethodHolder().getSourceFileName()); // source file name
753 out.writeInt(classSN); // class serial number
754 out.writeInt(lineNumber); // line number
755 }
756
757 protected void writeJavaThread(JavaThread jt, int index) throws IOException {
758 out.writeByte((byte) HPROF_GC_ROOT_THREAD_OBJ);
759 writeObjectID(jt.getThreadObj());
760 out.writeInt(index);
761 out.writeInt(DUMMY_STACK_TRACE_ID);
762 writeLocalJNIHandles(jt, index);
763 }
764
765 protected void writeLocalJNIHandles(JavaThread jt, int index) throws IOException {
766 final int threadIndex = index;
767 JNIHandleBlock blk = jt.activeHandles();
938
939 if (Assert.ASSERTS_ENABLED) {
940 Assert.that(cd != null, "can not get class data for " + klass.getName().asString() + klass.getAddress());
941 }
942 List fields = cd.fields;
943 int size = cd.instSize;
944 out.writeInt(size);
945 for (Iterator itr = fields.iterator(); itr.hasNext();) {
946 writeField((Field) itr.next(), instance);
947 }
948 }
949
950 //-- Internals only below this point
951
952 private void writeFieldDescriptors(List fields, InstanceKlass ik)
953 throws IOException {
954 // ik == null for instance fields.
955 out.writeShort((short) fields.size());
956 for (Iterator itr = fields.iterator(); itr.hasNext();) {
957 Field field = (Field) itr.next();
958 Symbol name = symTbl.probe(field.getID().getName());
959 writeSymbolID(name);
960 char typeCode = (char) field.getSignature().getByteAt(0);
961 int kind = signatureToHprofKind(typeCode);
962 out.writeByte((byte)kind);
963 if (ik != null) {
964 // static field
965 writeField(field, ik.getJavaMirror());
966 }
967 }
968 }
969
970 public static int signatureToHprofKind(char ch) {
971 switch (ch) {
972 case JVM_SIGNATURE_CLASS:
973 case JVM_SIGNATURE_ARRAY:
974 return HPROF_NORMAL_OBJECT;
975 case JVM_SIGNATURE_BOOLEAN:
976 return HPROF_BOOLEAN;
977 case JVM_SIGNATURE_CHAR:
978 return HPROF_CHAR;
1032 break;
1033 }
1034 default:
1035 throw new RuntimeException("should not reach here");
1036 }
1037 }
1038
1039 private void writeHeader(int tag, int len) throws IOException {
1040 out.writeByte((byte)tag);
1041 out.writeInt(0); // current ticks
1042 out.writeInt(len);
1043 }
1044
1045 private void writeDummyTrace() throws IOException {
1046 writeHeader(HPROF_TRACE, 3 * 4);
1047 out.writeInt(DUMMY_STACK_TRACE_ID);
1048 out.writeInt(0);
1049 out.writeInt(0);
1050 }
1051
1052 private void writeSymbols() throws IOException {
1053 try {
1054 symTbl.symbolsDo(new SymbolTable.SymbolVisitor() {
1055 public void visit(Symbol sym) {
1056 try {
1057 writeSymbol(sym);
1058 } catch (IOException exp) {
1059 throw new RuntimeException(exp);
1060 }
1061 }
1062 });
1063 } catch (RuntimeException re) {
1064 handleRuntimeException(re);
1065 }
1066 }
1067
1068 private void writeSymbol(Symbol sym) throws IOException {
1069 byte[] buf = sym.asString().getBytes("UTF-8");
1070 writeHeader(HPROF_UTF8, buf.length + OBJ_ID_SIZE);
1071 writeSymbolID(sym);
1072 out.write(buf);
1073 }
1074
1075 private void writeClasses() throws IOException {
1076 // write class list (id, name) association
1077 ClassLoaderDataGraph cldGraph = VM.getVM().getClassLoaderDataGraph();
1078 try {
1079 cldGraph.classesDo(new ClassLoaderDataGraph.ClassVisitor() {
1080 public void visit(Klass k) {
1081 try {
1082 Instance clazz = k.getJavaMirror();
1083 writeHeader(HPROF_LOAD_CLASS, 2 * (OBJ_ID_SIZE + 4));
1084 out.writeInt(serialNum);
1085 writeObjectID(clazz);
1086 KlassMap.add(serialNum - 1, k);
1087 out.writeInt(DUMMY_STACK_TRACE_ID);
1088 writeSymbolID(k.getName());
1089 serialNum++;
1090 } catch (IOException exp) {
1091 throw new RuntimeException(exp);
1092 }
1093 }
1101 private void writeFileHeader() throws IOException {
1102 // version string
1103 out.writeBytes(HPROF_HEADER_1_0_2);
1104 out.writeByte((byte)'\0');
1105
1106 // write identifier size. we use pointers as identifiers.
1107 out.writeInt(OBJ_ID_SIZE);
1108
1109 // timestamp -- file creation time.
1110 out.writeLong(System.currentTimeMillis());
1111 }
1112
1113 // writes unique ID for an object
1114 private void writeObjectID(Oop oop) throws IOException {
1115 OopHandle handle = (oop != null)? oop.getHandle() : null;
1116 long address = getAddressValue(handle);
1117 writeObjectID(address);
1118 }
1119
1120 private void writeSymbolID(Symbol sym) throws IOException {
1121 writeObjectID(getAddressValue(sym.getAddress()));
1122 }
1123
1124 private void writeObjectID(long address) throws IOException {
1125 if (OBJ_ID_SIZE == 4) {
1126 out.writeInt((int) address);
1127 } else {
1128 out.writeLong(address);
1129 }
1130 }
1131
1132 private long getAddressValue(Address addr) {
1133 return (addr == null)? 0L : dbg.getAddressValue(addr);
1134 }
1135
1136 // get all declared as well as inherited (directly/indirectly) fields
1137 private static List/*<Field>*/ getInstanceFields(InstanceKlass ik) {
1138 InstanceKlass klass = ik;
1139 List res = new ArrayList();
1140 while (klass != null) {
1178 case JVM_SIGNATURE_LONG:
1179 case JVM_SIGNATURE_DOUBLE:
1180 size += 8;
1181 break;
1182 default:
1183 throw new RuntimeException("should not reach here");
1184 }
1185 }
1186 return size;
1187 }
1188
1189 // We don't have allocation site info. We write a dummy
1190 // stack trace with this id.
1191 private static final int DUMMY_STACK_TRACE_ID = 1;
1192 private static final int EMPTY_FRAME_DEPTH = -1;
1193
1194 private DataOutputStream out;
1195 private FileOutputStream fos;
1196 private Debugger dbg;
1197 private ObjectHeap objectHeap;
1198 private SymbolTable symTbl;
1199 private ArrayList<Klass> KlassMap;
1200
1201 // oopSize of the debuggee
1202 private int OBJ_ID_SIZE;
1203
1204 // Added for hprof file format 1.0.2 support
1205 private boolean useSegmentedHeapDump;
1206 private long currentSegmentStart;
1207
1208 private long BOOLEAN_BASE_OFFSET;
1209 private long BYTE_BASE_OFFSET;
1210 private long CHAR_BASE_OFFSET;
1211 private long SHORT_BASE_OFFSET;
1212 private long INT_BASE_OFFSET;
1213 private long LONG_BASE_OFFSET;
1214 private long FLOAT_BASE_OFFSET;
1215 private long DOUBLE_BASE_OFFSET;
1216 private long OBJECT_BASE_OFFSET;
1217
1218 private long BOOLEAN_SIZE;
|
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;
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
385 public HeapHprofBinWriter() {
386 this.KlassMap = new ArrayList<Klass>();
387 this.names = new HashSet<Symbol>();
388 }
389
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();
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
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
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
773 protected void writeLocalJNIHandles(JavaThread jt, int index) throws IOException {
774 final int threadIndex = index;
775 JNIHandleBlock blk = jt.activeHandles();
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
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
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;
1040 break;
1041 }
1042 default:
1043 throw new RuntimeException("should not reach here");
1044 }
1045 }
1046
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
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
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
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
1090 private void writeSymbol(Symbol sym) throws IOException {
1091 // If name is already written don't write it again.
1092 if (names.add(sym)) {
1093 byte[] buf = sym.asString().getBytes("UTF-8");
1094 writeHeader(HPROF_UTF8, buf.length + OBJ_ID_SIZE);
1095 writeSymbolID(sym);
1096 out.write(buf);
1097 }
1098 }
1099
1100 private void writeClasses() throws IOException {
1101 // write class list (id, name) association
1102 ClassLoaderDataGraph cldGraph = VM.getVM().getClassLoaderDataGraph();
1103 try {
1104 cldGraph.classesDo(new ClassLoaderDataGraph.ClassVisitor() {
1105 public void visit(Klass k) {
1106 try {
1107 Instance clazz = k.getJavaMirror();
1108 writeHeader(HPROF_LOAD_CLASS, 2 * (OBJ_ID_SIZE + 4));
1109 out.writeInt(serialNum);
1110 writeObjectID(clazz);
1111 KlassMap.add(serialNum - 1, k);
1112 out.writeInt(DUMMY_STACK_TRACE_ID);
1113 writeSymbolID(k.getName());
1114 serialNum++;
1115 } catch (IOException exp) {
1116 throw new RuntimeException(exp);
1117 }
1118 }
1126 private void writeFileHeader() throws IOException {
1127 // version string
1128 out.writeBytes(HPROF_HEADER_1_0_2);
1129 out.writeByte((byte)'\0');
1130
1131 // write identifier size. we use pointers as identifiers.
1132 out.writeInt(OBJ_ID_SIZE);
1133
1134 // timestamp -- file creation time.
1135 out.writeLong(System.currentTimeMillis());
1136 }
1137
1138 // writes unique ID for an object
1139 private void writeObjectID(Oop oop) throws IOException {
1140 OopHandle handle = (oop != null)? oop.getHandle() : null;
1141 long address = getAddressValue(handle);
1142 writeObjectID(address);
1143 }
1144
1145 private void writeSymbolID(Symbol sym) throws IOException {
1146 assert names.contains(sym);
1147 writeObjectID(getAddressValue(sym.getAddress()));
1148 }
1149
1150 private void writeObjectID(long address) throws IOException {
1151 if (OBJ_ID_SIZE == 4) {
1152 out.writeInt((int) address);
1153 } else {
1154 out.writeLong(address);
1155 }
1156 }
1157
1158 private long getAddressValue(Address addr) {
1159 return (addr == null)? 0L : dbg.getAddressValue(addr);
1160 }
1161
1162 // get all declared as well as inherited (directly/indirectly) fields
1163 private static List/*<Field>*/ getInstanceFields(InstanceKlass ik) {
1164 InstanceKlass klass = ik;
1165 List res = new ArrayList();
1166 while (klass != null) {
1204 case JVM_SIGNATURE_LONG:
1205 case JVM_SIGNATURE_DOUBLE:
1206 size += 8;
1207 break;
1208 default:
1209 throw new RuntimeException("should not reach here");
1210 }
1211 }
1212 return size;
1213 }
1214
1215 // We don't have allocation site info. We write a dummy
1216 // stack trace with this id.
1217 private static final int DUMMY_STACK_TRACE_ID = 1;
1218 private static final int EMPTY_FRAME_DEPTH = -1;
1219
1220 private DataOutputStream out;
1221 private FileOutputStream fos;
1222 private Debugger dbg;
1223 private ObjectHeap objectHeap;
1224 private ArrayList<Klass> KlassMap;
1225
1226 // oopSize of the debuggee
1227 private int OBJ_ID_SIZE;
1228
1229 // Added for hprof file format 1.0.2 support
1230 private boolean useSegmentedHeapDump;
1231 private long currentSegmentStart;
1232
1233 private long BOOLEAN_BASE_OFFSET;
1234 private long BYTE_BASE_OFFSET;
1235 private long CHAR_BASE_OFFSET;
1236 private long SHORT_BASE_OFFSET;
1237 private long INT_BASE_OFFSET;
1238 private long LONG_BASE_OFFSET;
1239 private long FLOAT_BASE_OFFSET;
1240 private long DOUBLE_BASE_OFFSET;
1241 private long OBJECT_BASE_OFFSET;
1242
1243 private long BOOLEAN_SIZE;
|