< prev index next >

src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/HeapHprofBinWriter.java

Print this page




 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;
< prev index next >