• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 /*
18  * Preparation and completion of hprof data generation.  The output is
19  * written into two files and then combined.  This is necessary because
20  * we generate some of the data (strings and classes) while we dump the
21  * heap, and some analysis tools require that the class and string data
22  * appear first.
23  */
24 
25 #include "hprof.h"
26 
27 #include <cutils/open_memstream.h>
28 #include <errno.h>
29 #include <fcntl.h>
30 #include <stdio.h>
31 #include <string.h>
32 #include <sys/time.h>
33 #include <sys/uio.h>
34 #include <time.h>
35 #include <time.h>
36 #include <unistd.h>
37 
38 #include <set>
39 
40 #include "base/logging.h"
41 #include "base/stringprintf.h"
42 #include "base/unix_file/fd_file.h"
43 #include "class_linker.h"
44 #include "common_throws.h"
45 #include "debugger.h"
46 #include "dex_file-inl.h"
47 #include "gc/accounting/heap_bitmap.h"
48 #include "gc/heap.h"
49 #include "gc/space/space.h"
50 #include "globals.h"
51 #include "mirror/art_field-inl.h"
52 #include "mirror/class.h"
53 #include "mirror/class-inl.h"
54 #include "mirror/object-inl.h"
55 #include "object_utils.h"
56 #include "os.h"
57 #include "safe_map.h"
58 #include "scoped_thread_state_change.h"
59 #include "thread_list.h"
60 
61 namespace art {
62 
63 namespace hprof {
64 
65 #define UNIQUE_ERROR -((((uintptr_t)__func__) << 16 | __LINE__) & (0x7fffffff))
66 
67 #define HPROF_TIME 0
68 #define HPROF_NULL_STACK_TRACE   0
69 #define HPROF_NULL_THREAD        0
70 
71 #define U2_TO_BUF_BE(buf, offset, value) \
72     do { \
73       unsigned char* buf_ = (unsigned char*)(buf); \
74       int offset_ = static_cast<int>(offset); \
75       uint16_t value_ = (uint16_t)(value); \
76       buf_[offset_ + 0] = (unsigned char)(value_ >>  8); \
77       buf_[offset_ + 1] = (unsigned char)(value_      ); \
78     } while (0)
79 
80 #define U4_TO_BUF_BE(buf, offset, value) \
81     do { \
82       unsigned char* buf_ = (unsigned char*)(buf); \
83       int offset_ = static_cast<int>(offset); \
84       uint32_t value_ = (uint32_t)(value); \
85       buf_[offset_ + 0] = (unsigned char)(value_ >> 24); \
86       buf_[offset_ + 1] = (unsigned char)(value_ >> 16); \
87       buf_[offset_ + 2] = (unsigned char)(value_ >>  8); \
88       buf_[offset_ + 3] = (unsigned char)(value_      ); \
89     } while (0)
90 
91 #define U8_TO_BUF_BE(buf, offset, value) \
92     do { \
93       unsigned char* buf_ = (unsigned char*)(buf); \
94       int offset_ = static_cast<int>(offset); \
95       uint64_t value_ = (uint64_t)(value); \
96       buf_[offset_ + 0] = (unsigned char)(value_ >> 56); \
97       buf_[offset_ + 1] = (unsigned char)(value_ >> 48); \
98       buf_[offset_ + 2] = (unsigned char)(value_ >> 40); \
99       buf_[offset_ + 3] = (unsigned char)(value_ >> 32); \
100       buf_[offset_ + 4] = (unsigned char)(value_ >> 24); \
101       buf_[offset_ + 5] = (unsigned char)(value_ >> 16); \
102       buf_[offset_ + 6] = (unsigned char)(value_ >>  8); \
103       buf_[offset_ + 7] = (unsigned char)(value_      ); \
104     } while (0)
105 
106 enum HprofTag {
107   HPROF_TAG_STRING = 0x01,
108   HPROF_TAG_LOAD_CLASS = 0x02,
109   HPROF_TAG_UNLOAD_CLASS = 0x03,
110   HPROF_TAG_STACK_FRAME = 0x04,
111   HPROF_TAG_STACK_TRACE = 0x05,
112   HPROF_TAG_ALLOC_SITES = 0x06,
113   HPROF_TAG_HEAP_SUMMARY = 0x07,
114   HPROF_TAG_START_THREAD = 0x0A,
115   HPROF_TAG_END_THREAD = 0x0B,
116   HPROF_TAG_HEAP_DUMP = 0x0C,
117   HPROF_TAG_HEAP_DUMP_SEGMENT = 0x1C,
118   HPROF_TAG_HEAP_DUMP_END = 0x2C,
119   HPROF_TAG_CPU_SAMPLES = 0x0D,
120   HPROF_TAG_CONTROL_SETTINGS = 0x0E,
121 };
122 
123 // Values for the first byte of HEAP_DUMP and HEAP_DUMP_SEGMENT records:
124 enum HprofHeapTag {
125   // Traditional.
126   HPROF_ROOT_UNKNOWN = 0xFF,
127   HPROF_ROOT_JNI_GLOBAL = 0x01,
128   HPROF_ROOT_JNI_LOCAL = 0x02,
129   HPROF_ROOT_JAVA_FRAME = 0x03,
130   HPROF_ROOT_NATIVE_STACK = 0x04,
131   HPROF_ROOT_STICKY_CLASS = 0x05,
132   HPROF_ROOT_THREAD_BLOCK = 0x06,
133   HPROF_ROOT_MONITOR_USED = 0x07,
134   HPROF_ROOT_THREAD_OBJECT = 0x08,
135   HPROF_CLASS_DUMP = 0x20,
136   HPROF_INSTANCE_DUMP = 0x21,
137   HPROF_OBJECT_ARRAY_DUMP = 0x22,
138   HPROF_PRIMITIVE_ARRAY_DUMP = 0x23,
139 
140   // Android.
141   HPROF_HEAP_DUMP_INFO = 0xfe,
142   HPROF_ROOT_INTERNED_STRING = 0x89,
143   HPROF_ROOT_FINALIZING = 0x8a,  // Obsolete.
144   HPROF_ROOT_DEBUGGER = 0x8b,
145   HPROF_ROOT_REFERENCE_CLEANUP = 0x8c,  // Obsolete.
146   HPROF_ROOT_VM_INTERNAL = 0x8d,
147   HPROF_ROOT_JNI_MONITOR = 0x8e,
148   HPROF_UNREACHABLE = 0x90,  // Obsolete.
149   HPROF_PRIMITIVE_ARRAY_NODATA_DUMP = 0xc3,  // Obsolete.
150 };
151 
152 enum HprofHeapId {
153   HPROF_HEAP_DEFAULT = 0,
154   HPROF_HEAP_ZYGOTE = 'Z',
155   HPROF_HEAP_APP = 'A'
156 };
157 
158 enum HprofBasicType {
159   hprof_basic_object = 2,
160   hprof_basic_boolean = 4,
161   hprof_basic_char = 5,
162   hprof_basic_float = 6,
163   hprof_basic_double = 7,
164   hprof_basic_byte = 8,
165   hprof_basic_short = 9,
166   hprof_basic_int = 10,
167   hprof_basic_long = 11,
168 };
169 
170 typedef uint32_t HprofId;
171 typedef HprofId HprofStringId;
172 typedef HprofId HprofObjectId;
173 typedef HprofId HprofClassObjectId;
174 typedef std::set<mirror::Class*> ClassSet;
175 typedef std::set<mirror::Class*>::iterator ClassSetIterator;
176 typedef SafeMap<std::string, size_t> StringMap;
177 typedef SafeMap<std::string, size_t>::iterator StringMapIterator;
178 
179 // Represents a top-level hprof record, whose serialized format is:
180 // U1  TAG: denoting the type of the record
181 // U4  TIME: number of microseconds since the time stamp in the header
182 // U4  LENGTH: number of bytes that follow this uint32_t field and belong to this record
183 // U1* BODY: as many bytes as specified in the above uint32_t field
184 class HprofRecord {
185  public:
HprofRecord()186   HprofRecord() {
187     dirty_ = false;
188     alloc_length_ = 128;
189     body_ = reinterpret_cast<unsigned char*>(malloc(alloc_length_));
190     fp_ = NULL;
191   }
192 
~HprofRecord()193   ~HprofRecord() {
194     free(body_);
195   }
196 
StartNewRecord(FILE * fp,uint8_t tag,uint32_t time)197   int StartNewRecord(FILE* fp, uint8_t tag, uint32_t time) {
198     int rc = Flush();
199     if (rc != 0) {
200       return rc;
201     }
202 
203     fp_ = fp;
204     tag_ = tag;
205     time_ = time;
206     length_ = 0;
207     dirty_ = true;
208     return 0;
209   }
210 
Flush()211   int Flush() {
212     if (dirty_) {
213       unsigned char headBuf[sizeof(uint8_t) + 2 * sizeof(uint32_t)];
214 
215       headBuf[0] = tag_;
216       U4_TO_BUF_BE(headBuf, 1, time_);
217       U4_TO_BUF_BE(headBuf, 5, length_);
218 
219       int nb = fwrite(headBuf, 1, sizeof(headBuf), fp_);
220       if (nb != sizeof(headBuf)) {
221         return UNIQUE_ERROR;
222       }
223       nb = fwrite(body_, 1, length_, fp_);
224       if (nb != static_cast<int>(length_)) {
225         return UNIQUE_ERROR;
226       }
227 
228       dirty_ = false;
229     }
230     // TODO if we used less than half (or whatever) of allocLen, shrink the buffer.
231     return 0;
232   }
233 
AddU1(uint8_t value)234   int AddU1(uint8_t value) {
235     int err = GuaranteeRecordAppend(1);
236     if (err != 0) {
237       return err;
238     }
239 
240     body_[length_++] = value;
241     return 0;
242   }
243 
AddU2(uint16_t value)244   int AddU2(uint16_t value) {
245     return AddU2List(&value, 1);
246   }
247 
AddU4(uint32_t value)248   int AddU4(uint32_t value) {
249     return AddU4List(&value, 1);
250   }
251 
AddU8(uint64_t value)252   int AddU8(uint64_t value) {
253     return AddU8List(&value, 1);
254   }
255 
AddId(HprofObjectId value)256   int AddId(HprofObjectId value) {
257     return AddU4((uint32_t) value);
258   }
259 
AddU1List(const uint8_t * values,size_t numValues)260   int AddU1List(const uint8_t* values, size_t numValues) {
261     int err = GuaranteeRecordAppend(numValues);
262     if (err != 0) {
263       return err;
264     }
265 
266     memcpy(body_ + length_, values, numValues);
267     length_ += numValues;
268     return 0;
269   }
270 
AddU2List(const uint16_t * values,size_t numValues)271   int AddU2List(const uint16_t* values, size_t numValues) {
272     int err = GuaranteeRecordAppend(numValues * 2);
273     if (err != 0) {
274       return err;
275     }
276 
277     unsigned char* insert = body_ + length_;
278     for (size_t i = 0; i < numValues; ++i) {
279       U2_TO_BUF_BE(insert, 0, *values++);
280       insert += sizeof(*values);
281     }
282     length_ += numValues * 2;
283     return 0;
284   }
285 
AddU4List(const uint32_t * values,size_t numValues)286   int AddU4List(const uint32_t* values, size_t numValues) {
287     int err = GuaranteeRecordAppend(numValues * 4);
288     if (err != 0) {
289       return err;
290     }
291 
292     unsigned char* insert = body_ + length_;
293     for (size_t i = 0; i < numValues; ++i) {
294       U4_TO_BUF_BE(insert, 0, *values++);
295       insert += sizeof(*values);
296     }
297     length_ += numValues * 4;
298     return 0;
299   }
300 
UpdateU4(size_t offset,uint32_t new_value)301   void UpdateU4(size_t offset, uint32_t new_value) {
302     U4_TO_BUF_BE(body_, offset, new_value);
303   }
304 
AddU8List(const uint64_t * values,size_t numValues)305   int AddU8List(const uint64_t* values, size_t numValues) {
306     int err = GuaranteeRecordAppend(numValues * 8);
307     if (err != 0) {
308       return err;
309     }
310 
311     unsigned char* insert = body_ + length_;
312     for (size_t i = 0; i < numValues; ++i) {
313       U8_TO_BUF_BE(insert, 0, *values++);
314       insert += sizeof(*values);
315     }
316     length_ += numValues * 8;
317     return 0;
318   }
319 
AddIdList(const HprofObjectId * values,size_t numValues)320   int AddIdList(const HprofObjectId* values, size_t numValues) {
321     return AddU4List((const uint32_t*) values, numValues);
322   }
323 
AddUtf8String(const char * str)324   int AddUtf8String(const char* str) {
325     // The terminating NUL character is NOT written.
326     return AddU1List((const uint8_t*)str, strlen(str));
327   }
328 
Size() const329   size_t Size() const {
330     return length_;
331   }
332 
333  private:
GuaranteeRecordAppend(size_t nmore)334   int GuaranteeRecordAppend(size_t nmore) {
335     size_t minSize = length_ + nmore;
336     if (minSize > alloc_length_) {
337       size_t newAllocLen = alloc_length_ * 2;
338       if (newAllocLen < minSize) {
339         newAllocLen = alloc_length_ + nmore + nmore/2;
340       }
341       unsigned char* newBody = (unsigned char*)realloc(body_, newAllocLen);
342       if (newBody != NULL) {
343         body_ = newBody;
344         alloc_length_ = newAllocLen;
345       } else {
346         // TODO: set an error flag so future ops will fail
347         return UNIQUE_ERROR;
348       }
349     }
350 
351     CHECK_LE(length_ + nmore, alloc_length_);
352     return 0;
353   }
354 
355   size_t alloc_length_;
356   unsigned char* body_;
357 
358   FILE* fp_;
359   uint8_t tag_;
360   uint32_t time_;
361   size_t length_;
362   bool dirty_;
363 
364   DISALLOW_COPY_AND_ASSIGN(HprofRecord);
365 };
366 
367 class Hprof {
368  public:
Hprof(const char * output_filename,int fd,bool direct_to_ddms)369   Hprof(const char* output_filename, int fd, bool direct_to_ddms)
370       : filename_(output_filename),
371         fd_(fd),
372         direct_to_ddms_(direct_to_ddms),
373         start_ns_(NanoTime()),
374         current_record_(),
375         gc_thread_serial_number_(0),
376         gc_scan_state_(0),
377         current_heap_(HPROF_HEAP_DEFAULT),
378         objects_in_segment_(0),
379         header_fp_(NULL),
380         header_data_ptr_(NULL),
381         header_data_size_(0),
382         body_fp_(NULL),
383         body_data_ptr_(NULL),
384         body_data_size_(0),
385         next_string_id_(0x400000) {
386     LOG(INFO) << "hprof: heap dump \"" << filename_ << "\" starting...";
387 
388     header_fp_ = open_memstream(&header_data_ptr_, &header_data_size_);
389     if (header_fp_ == NULL) {
390       PLOG(FATAL) << "header open_memstream failed";
391     }
392 
393     body_fp_ = open_memstream(&body_data_ptr_, &body_data_size_);
394     if (body_fp_ == NULL) {
395       PLOG(FATAL) << "body open_memstream failed";
396     }
397   }
398 
~Hprof()399   ~Hprof() {
400     if (header_fp_ != NULL) {
401       fclose(header_fp_);
402     }
403     if (body_fp_ != NULL) {
404       fclose(body_fp_);
405     }
406     free(header_data_ptr_);
407     free(body_data_ptr_);
408   }
409 
Dump()410   void Dump()
411       EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_)
412       LOCKS_EXCLUDED(Locks::heap_bitmap_lock_) {
413     // Walk the roots and the heap.
414     current_record_.StartNewRecord(body_fp_, HPROF_TAG_HEAP_DUMP_SEGMENT, HPROF_TIME);
415     Runtime::Current()->VisitRoots(RootVisitor, this, false, false);
416     Thread* self = Thread::Current();
417     {
418       WriterMutexLock mu(self, *Locks::heap_bitmap_lock_);
419       Runtime::Current()->GetHeap()->FlushAllocStack();
420     }
421     {
422       ReaderMutexLock mu(self, *Locks::heap_bitmap_lock_);
423       Runtime::Current()->GetHeap()->GetLiveBitmap()->Walk(HeapBitmapCallback, this);
424     }
425     current_record_.StartNewRecord(body_fp_, HPROF_TAG_HEAP_DUMP_END, HPROF_TIME);
426     current_record_.Flush();
427     fflush(body_fp_);
428 
429     // Write the header.
430     WriteFixedHeader();
431     // Write the string and class tables, and any stack traces, to the header.
432     // (jhat requires that these appear before any of the data in the body that refers to them.)
433     WriteStringTable();
434     WriteClassTable();
435     WriteStackTraces();
436     current_record_.Flush();
437     fflush(header_fp_);
438 
439     bool okay = true;
440     if (direct_to_ddms_) {
441       // Send the data off to DDMS.
442       iovec iov[2];
443       iov[0].iov_base = header_data_ptr_;
444       iov[0].iov_len = header_data_size_;
445       iov[1].iov_base = body_data_ptr_;
446       iov[1].iov_len = body_data_size_;
447       Dbg::DdmSendChunkV(CHUNK_TYPE("HPDS"), iov, 2);
448     } else {
449       // Where exactly are we writing to?
450       int out_fd;
451       if (fd_ >= 0) {
452         out_fd = dup(fd_);
453         if (out_fd < 0) {
454           ThrowRuntimeException("Couldn't dump heap; dup(%d) failed: %s", fd_, strerror(errno));
455           return;
456         }
457       } else {
458         out_fd = open(filename_.c_str(), O_WRONLY|O_CREAT|O_TRUNC, 0644);
459         if (out_fd < 0) {
460           ThrowRuntimeException("Couldn't dump heap; open(\"%s\") failed: %s", filename_.c_str(),
461                                 strerror(errno));
462           return;
463         }
464       }
465 
466       UniquePtr<File> file(new File(out_fd, filename_));
467       okay = file->WriteFully(header_data_ptr_, header_data_size_) &&
468           file->WriteFully(body_data_ptr_, body_data_size_);
469       if (!okay) {
470         std::string msg(StringPrintf("Couldn't dump heap; writing \"%s\" failed: %s",
471                                      filename_.c_str(), strerror(errno)));
472         ThrowRuntimeException("%s", msg.c_str());
473         LOG(ERROR) << msg;
474       }
475     }
476 
477     // Throw out a log message for the benefit of "runhat".
478     if (okay) {
479       uint64_t duration = NanoTime() - start_ns_;
480       LOG(INFO) << "hprof: heap dump completed ("
481           << PrettySize(header_data_size_ + body_data_size_ + 1023)
482           << ") in " << PrettyDuration(duration);
483     }
484   }
485 
486  private:
RootVisitor(const mirror::Object * obj,void * arg)487   static void RootVisitor(const mirror::Object* obj, void* arg)
488       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
489     CHECK(arg != NULL);
490     Hprof* hprof = reinterpret_cast<Hprof*>(arg);
491     hprof->VisitRoot(obj);
492   }
493 
HeapBitmapCallback(mirror::Object * obj,void * arg)494   static void HeapBitmapCallback(mirror::Object* obj, void* arg)
495       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
496     CHECK(obj != NULL);
497     CHECK(arg != NULL);
498     Hprof* hprof = reinterpret_cast<Hprof*>(arg);
499     hprof->DumpHeapObject(obj);
500   }
501 
502   void VisitRoot(const mirror::Object* obj) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
503 
504   int DumpHeapObject(mirror::Object* obj) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
505 
Finish()506   void Finish() {
507   }
508 
WriteClassTable()509   int WriteClassTable() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
510     HprofRecord* rec = &current_record_;
511     uint32_t nextSerialNumber = 1;
512 
513     for (ClassSetIterator it = classes_.begin(); it != classes_.end(); ++it) {
514       const mirror::Class* c = *it;
515       CHECK(c != NULL);
516 
517       int err = current_record_.StartNewRecord(header_fp_, HPROF_TAG_LOAD_CLASS, HPROF_TIME);
518       if (err != 0) {
519         return err;
520       }
521 
522       // LOAD CLASS format:
523       // U4: class serial number (always > 0)
524       // ID: class object ID. We use the address of the class object structure as its ID.
525       // U4: stack trace serial number
526       // ID: class name string ID
527       rec->AddU4(nextSerialNumber++);
528       rec->AddId((HprofClassObjectId) c);
529       rec->AddU4(HPROF_NULL_STACK_TRACE);
530       rec->AddId(LookupClassNameId(c));
531     }
532 
533     return 0;
534   }
535 
WriteStringTable()536   int WriteStringTable() {
537     HprofRecord* rec = &current_record_;
538 
539     for (StringMapIterator it = strings_.begin(); it != strings_.end(); ++it) {
540       std::string string((*it).first);
541       size_t id = (*it).second;
542 
543       int err = current_record_.StartNewRecord(header_fp_, HPROF_TAG_STRING, HPROF_TIME);
544       if (err != 0) {
545         return err;
546       }
547 
548       // STRING format:
549       // ID:  ID for this string
550       // U1*: UTF8 characters for string (NOT NULL terminated)
551       //      (the record format encodes the length)
552       err = rec->AddU4(id);
553       if (err != 0) {
554         return err;
555       }
556       err = rec->AddUtf8String(string.c_str());
557       if (err != 0) {
558         return err;
559       }
560     }
561 
562     return 0;
563   }
564 
StartNewHeapDumpSegment()565   void StartNewHeapDumpSegment() {
566     // This flushes the old segment and starts a new one.
567     current_record_.StartNewRecord(body_fp_, HPROF_TAG_HEAP_DUMP_SEGMENT, HPROF_TIME);
568     objects_in_segment_ = 0;
569 
570     // Starting a new HEAP_DUMP resets the heap to default.
571     current_heap_ = HPROF_HEAP_DEFAULT;
572   }
573 
574   int MarkRootObject(const mirror::Object* obj, jobject jniObj);
575 
LookupClassId(mirror::Class * c)576   HprofClassObjectId LookupClassId(mirror::Class* c)
577       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
578     if (c == NULL) {
579       // c is the superclass of java.lang.Object or a primitive
580       return (HprofClassObjectId)0;
581     }
582 
583     std::pair<ClassSetIterator, bool> result = classes_.insert(c);
584     const mirror::Class* present = *result.first;
585 
586     // Make sure that we've assigned a string ID for this class' name
587     LookupClassNameId(c);
588 
589     CHECK_EQ(present, c);
590     return (HprofStringId) present;
591   }
592 
LookupStringId(mirror::String * string)593   HprofStringId LookupStringId(mirror::String* string) {
594     return LookupStringId(string->ToModifiedUtf8());
595   }
596 
LookupStringId(const char * string)597   HprofStringId LookupStringId(const char* string) {
598     return LookupStringId(std::string(string));
599   }
600 
LookupStringId(const std::string & string)601   HprofStringId LookupStringId(const std::string& string) {
602     StringMapIterator it = strings_.find(string);
603     if (it != strings_.end()) {
604       return it->second;
605     }
606     HprofStringId id = next_string_id_++;
607     strings_.Put(string, id);
608     return id;
609   }
610 
LookupClassNameId(const mirror::Class * c)611   HprofStringId LookupClassNameId(const mirror::Class* c)
612       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
613     return LookupStringId(PrettyDescriptor(c));
614   }
615 
WriteFixedHeader()616   void WriteFixedHeader() {
617     char magic[] = "JAVA PROFILE 1.0.3";
618     unsigned char buf[4];
619 
620     // Write the file header.
621     // U1: NUL-terminated magic string.
622     fwrite(magic, 1, sizeof(magic), header_fp_);
623 
624     // U4: size of identifiers.  We're using addresses as IDs, so make sure a pointer fits.
625     U4_TO_BUF_BE(buf, 0, sizeof(void*));
626     fwrite(buf, 1, sizeof(uint32_t), header_fp_);
627 
628     // The current time, in milliseconds since 0:00 GMT, 1/1/70.
629     timeval now;
630     uint64_t nowMs;
631     if (gettimeofday(&now, NULL) < 0) {
632       nowMs = 0;
633     } else {
634       nowMs = (uint64_t)now.tv_sec * 1000 + now.tv_usec / 1000;
635     }
636 
637     // U4: high word of the 64-bit time.
638     U4_TO_BUF_BE(buf, 0, (uint32_t)(nowMs >> 32));
639     fwrite(buf, 1, sizeof(uint32_t), header_fp_);
640 
641     // U4: low word of the 64-bit time.
642     U4_TO_BUF_BE(buf, 0, (uint32_t)(nowMs & 0xffffffffULL));
643     fwrite(buf, 1, sizeof(uint32_t), header_fp_);  // xxx fix the time
644   }
645 
WriteStackTraces()646   void WriteStackTraces() {
647     // Write a dummy stack trace record so the analysis tools don't freak out.
648     current_record_.StartNewRecord(header_fp_, HPROF_TAG_STACK_TRACE, HPROF_TIME);
649     current_record_.AddU4(HPROF_NULL_STACK_TRACE);
650     current_record_.AddU4(HPROF_NULL_THREAD);
651     current_record_.AddU4(0);    // no frames
652   }
653 
654   // If direct_to_ddms_ is set, "filename_" and "fd" will be ignored.
655   // Otherwise, "filename_" must be valid, though if "fd" >= 0 it will
656   // only be used for debug messages.
657   std::string filename_;
658   int fd_;
659   bool direct_to_ddms_;
660 
661   uint64_t start_ns_;
662 
663   HprofRecord current_record_;
664 
665   uint32_t gc_thread_serial_number_;
666   uint8_t gc_scan_state_;
667   HprofHeapId current_heap_;  // Which heap we're currently dumping.
668   size_t objects_in_segment_;
669 
670   FILE* header_fp_;
671   char* header_data_ptr_;
672   size_t header_data_size_;
673 
674   FILE* body_fp_;
675   char* body_data_ptr_;
676   size_t body_data_size_;
677 
678   ClassSet classes_;
679   size_t next_string_id_;
680   StringMap strings_;
681 
682   DISALLOW_COPY_AND_ASSIGN(Hprof);
683 };
684 
685 #define OBJECTS_PER_SEGMENT     ((size_t)128)
686 #define BYTES_PER_SEGMENT       ((size_t)4096)
687 
688 // The static field-name for the synthetic object generated to account
689 // for class static overhead.
690 #define STATIC_OVERHEAD_NAME    "$staticOverhead"
691 // The ID for the synthetic object generated to account for class static overhead.
692 #define CLASS_STATICS_ID(c) ((HprofObjectId)(((uint32_t)(c)) | 1))
693 
SignatureToBasicTypeAndSize(const char * sig,size_t * sizeOut)694 static HprofBasicType SignatureToBasicTypeAndSize(const char* sig, size_t* sizeOut) {
695   char c = sig[0];
696   HprofBasicType ret;
697   size_t size;
698 
699   switch (c) {
700   case '[':
701   case 'L': ret = hprof_basic_object;  size = 4; break;
702   case 'Z': ret = hprof_basic_boolean; size = 1; break;
703   case 'C': ret = hprof_basic_char;    size = 2; break;
704   case 'F': ret = hprof_basic_float;   size = 4; break;
705   case 'D': ret = hprof_basic_double;  size = 8; break;
706   case 'B': ret = hprof_basic_byte;    size = 1; break;
707   case 'S': ret = hprof_basic_short;   size = 2; break;
708   default: CHECK(false);
709   case 'I': ret = hprof_basic_int;     size = 4; break;
710   case 'J': ret = hprof_basic_long;    size = 8; break;
711   }
712 
713   if (sizeOut != NULL) {
714     *sizeOut = size;
715   }
716 
717   return ret;
718 }
719 
PrimitiveToBasicTypeAndSize(Primitive::Type prim,size_t * sizeOut)720 static HprofBasicType PrimitiveToBasicTypeAndSize(Primitive::Type prim, size_t* sizeOut) {
721   HprofBasicType ret;
722   size_t size;
723 
724   switch (prim) {
725   case Primitive::kPrimBoolean: ret = hprof_basic_boolean; size = 1; break;
726   case Primitive::kPrimChar:    ret = hprof_basic_char;    size = 2; break;
727   case Primitive::kPrimFloat:   ret = hprof_basic_float;   size = 4; break;
728   case Primitive::kPrimDouble:  ret = hprof_basic_double;  size = 8; break;
729   case Primitive::kPrimByte:    ret = hprof_basic_byte;    size = 1; break;
730   case Primitive::kPrimShort:   ret = hprof_basic_short;   size = 2; break;
731   default: CHECK(false);
732   case Primitive::kPrimInt:     ret = hprof_basic_int;     size = 4; break;
733   case Primitive::kPrimLong:    ret = hprof_basic_long;    size = 8; break;
734   }
735 
736   if (sizeOut != NULL) {
737     *sizeOut = size;
738   }
739 
740   return ret;
741 }
742 
743 // Always called when marking objects, but only does
744 // something when ctx->gc_scan_state_ is non-zero, which is usually
745 // only true when marking the root set or unreachable
746 // objects.  Used to add rootset references to obj.
MarkRootObject(const mirror::Object * obj,jobject jniObj)747 int Hprof::MarkRootObject(const mirror::Object* obj, jobject jniObj) {
748   HprofRecord* rec = &current_record_;
749   HprofHeapTag heapTag = (HprofHeapTag)gc_scan_state_;
750 
751   if (heapTag == 0) {
752     return 0;
753   }
754 
755   if (objects_in_segment_ >= OBJECTS_PER_SEGMENT || rec->Size() >= BYTES_PER_SEGMENT) {
756     StartNewHeapDumpSegment();
757   }
758 
759   switch (heapTag) {
760   // ID: object ID
761   case HPROF_ROOT_UNKNOWN:
762   case HPROF_ROOT_STICKY_CLASS:
763   case HPROF_ROOT_MONITOR_USED:
764   case HPROF_ROOT_INTERNED_STRING:
765   case HPROF_ROOT_DEBUGGER:
766   case HPROF_ROOT_VM_INTERNAL:
767     rec->AddU1(heapTag);
768     rec->AddId((HprofObjectId)obj);
769     break;
770 
771   // ID: object ID
772   // ID: JNI global ref ID
773   case HPROF_ROOT_JNI_GLOBAL:
774     rec->AddU1(heapTag);
775     rec->AddId((HprofObjectId)obj);
776     rec->AddId((HprofId)jniObj);
777     break;
778 
779   // ID: object ID
780   // U4: thread serial number
781   // U4: frame number in stack trace (-1 for empty)
782   case HPROF_ROOT_JNI_LOCAL:
783   case HPROF_ROOT_JNI_MONITOR:
784   case HPROF_ROOT_JAVA_FRAME:
785     rec->AddU1(heapTag);
786     rec->AddId((HprofObjectId)obj);
787     rec->AddU4(gc_thread_serial_number_);
788     rec->AddU4((uint32_t)-1);
789     break;
790 
791   // ID: object ID
792   // U4: thread serial number
793   case HPROF_ROOT_NATIVE_STACK:
794   case HPROF_ROOT_THREAD_BLOCK:
795     rec->AddU1(heapTag);
796     rec->AddId((HprofObjectId)obj);
797     rec->AddU4(gc_thread_serial_number_);
798     break;
799 
800   // ID: thread object ID
801   // U4: thread serial number
802   // U4: stack trace serial number
803   case HPROF_ROOT_THREAD_OBJECT:
804     rec->AddU1(heapTag);
805     rec->AddId((HprofObjectId)obj);
806     rec->AddU4(gc_thread_serial_number_);
807     rec->AddU4((uint32_t)-1);    // xxx
808     break;
809 
810   case HPROF_CLASS_DUMP:
811   case HPROF_INSTANCE_DUMP:
812   case HPROF_OBJECT_ARRAY_DUMP:
813   case HPROF_PRIMITIVE_ARRAY_DUMP:
814   case HPROF_HEAP_DUMP_INFO:
815   case HPROF_PRIMITIVE_ARRAY_NODATA_DUMP:
816     // Ignored.
817     break;
818 
819   case HPROF_ROOT_FINALIZING:
820   case HPROF_ROOT_REFERENCE_CLEANUP:
821   case HPROF_UNREACHABLE:
822     LOG(FATAL) << "obsolete tag " << static_cast<int>(heapTag);
823     break;
824   }
825 
826   ++objects_in_segment_;
827   return 0;
828 }
829 
StackTraceSerialNumber(const mirror::Object *)830 static int StackTraceSerialNumber(const mirror::Object* /*obj*/) {
831   return HPROF_NULL_STACK_TRACE;
832 }
833 
DumpHeapObject(mirror::Object * obj)834 int Hprof::DumpHeapObject(mirror::Object* obj) {
835   HprofRecord* rec = &current_record_;
836   HprofHeapId desiredHeap = false ? HPROF_HEAP_ZYGOTE : HPROF_HEAP_APP;  // TODO: zygote objects?
837 
838   if (objects_in_segment_ >= OBJECTS_PER_SEGMENT || rec->Size() >= BYTES_PER_SEGMENT) {
839     StartNewHeapDumpSegment();
840   }
841 
842   if (desiredHeap != current_heap_) {
843     HprofStringId nameId;
844 
845     // This object is in a different heap than the current one.
846     // Emit a HEAP_DUMP_INFO tag to change heaps.
847     rec->AddU1(HPROF_HEAP_DUMP_INFO);
848     rec->AddU4((uint32_t)desiredHeap);   // uint32_t: heap id
849     switch (desiredHeap) {
850     case HPROF_HEAP_APP:
851       nameId = LookupStringId("app");
852       break;
853     case HPROF_HEAP_ZYGOTE:
854       nameId = LookupStringId("zygote");
855       break;
856     default:
857       // Internal error
858       LOG(ERROR) << "Unexpected desiredHeap";
859       nameId = LookupStringId("<ILLEGAL>");
860       break;
861     }
862     rec->AddId(nameId);
863     current_heap_ = desiredHeap;
864   }
865 
866   mirror::Class* c = obj->GetClass();
867   if (c == NULL) {
868     // This object will bother HprofReader, because it has a NULL
869     // class, so just don't dump it. It could be
870     // gDvm.unlinkedJavaLangClass or it could be an object just
871     // allocated which hasn't been initialized yet.
872   } else {
873     if (obj->IsClass()) {
874       mirror::Class* thisClass = obj->AsClass();
875       // obj is a ClassObject.
876       size_t sFieldCount = thisClass->NumStaticFields();
877       if (sFieldCount != 0) {
878         int byteLength = sFieldCount*sizeof(JValue);  // TODO bogus; fields are packed
879         // Create a byte array to reflect the allocation of the
880         // StaticField array at the end of this class.
881         rec->AddU1(HPROF_PRIMITIVE_ARRAY_DUMP);
882         rec->AddId(CLASS_STATICS_ID(obj));
883         rec->AddU4(StackTraceSerialNumber(obj));
884         rec->AddU4(byteLength);
885         rec->AddU1(hprof_basic_byte);
886         for (int i = 0; i < byteLength; ++i) {
887           rec->AddU1(0);
888         }
889       }
890 
891       rec->AddU1(HPROF_CLASS_DUMP);
892       rec->AddId(LookupClassId(thisClass));
893       rec->AddU4(StackTraceSerialNumber(thisClass));
894       rec->AddId(LookupClassId(thisClass->GetSuperClass()));
895       rec->AddId((HprofObjectId)thisClass->GetClassLoader());
896       rec->AddId((HprofObjectId)0);    // no signer
897       rec->AddId((HprofObjectId)0);    // no prot domain
898       rec->AddId((HprofId)0);           // reserved
899       rec->AddId((HprofId)0);           // reserved
900       if (thisClass->IsClassClass()) {
901         // ClassObjects have their static fields appended, so aren't all the same size.
902         // But they're at least this size.
903         rec->AddU4(sizeof(mirror::Class));  // instance size
904       } else if (thisClass->IsArrayClass() || thisClass->IsPrimitive()) {
905         rec->AddU4(0);
906       } else {
907         rec->AddU4(thisClass->GetObjectSize());  // instance size
908       }
909 
910       rec->AddU2(0);  // empty const pool
911 
912       FieldHelper fh;
913 
914       // Static fields
915       if (sFieldCount == 0) {
916         rec->AddU2((uint16_t)0);
917       } else {
918         rec->AddU2((uint16_t)(sFieldCount+1));
919         rec->AddId(LookupStringId(STATIC_OVERHEAD_NAME));
920         rec->AddU1(hprof_basic_object);
921         rec->AddId(CLASS_STATICS_ID(obj));
922 
923         for (size_t i = 0; i < sFieldCount; ++i) {
924           mirror::ArtField* f = thisClass->GetStaticField(i);
925           fh.ChangeField(f);
926 
927           size_t size;
928           HprofBasicType t = SignatureToBasicTypeAndSize(fh.GetTypeDescriptor(), &size);
929           rec->AddId(LookupStringId(fh.GetName()));
930           rec->AddU1(t);
931           if (size == 1) {
932             rec->AddU1(static_cast<uint8_t>(f->Get32(thisClass)));
933           } else if (size == 2) {
934             rec->AddU2(static_cast<uint16_t>(f->Get32(thisClass)));
935           } else if (size == 4) {
936             rec->AddU4(f->Get32(thisClass));
937           } else if (size == 8) {
938             rec->AddU8(f->Get64(thisClass));
939           } else {
940             CHECK(false);
941           }
942         }
943       }
944 
945       // Instance fields for this class (no superclass fields)
946       int iFieldCount = thisClass->IsObjectClass() ? 0 : thisClass->NumInstanceFields();
947       rec->AddU2((uint16_t)iFieldCount);
948       for (int i = 0; i < iFieldCount; ++i) {
949         mirror::ArtField* f = thisClass->GetInstanceField(i);
950         fh.ChangeField(f);
951         HprofBasicType t = SignatureToBasicTypeAndSize(fh.GetTypeDescriptor(), NULL);
952         rec->AddId(LookupStringId(fh.GetName()));
953         rec->AddU1(t);
954       }
955     } else if (c->IsArrayClass()) {
956       const mirror::Array* aobj = obj->AsArray();
957       uint32_t length = aobj->GetLength();
958 
959       if (obj->IsObjectArray()) {
960         // obj is an object array.
961         rec->AddU1(HPROF_OBJECT_ARRAY_DUMP);
962 
963         rec->AddId((HprofObjectId)obj);
964         rec->AddU4(StackTraceSerialNumber(obj));
965         rec->AddU4(length);
966         rec->AddId(LookupClassId(c));
967 
968         // Dump the elements, which are always objects or NULL.
969         rec->AddIdList((const HprofObjectId*)aobj->GetRawData(sizeof(mirror::Object*)), length);
970       } else {
971         size_t size;
972         HprofBasicType t = PrimitiveToBasicTypeAndSize(c->GetComponentType()->GetPrimitiveType(), &size);
973 
974         // obj is a primitive array.
975         rec->AddU1(HPROF_PRIMITIVE_ARRAY_DUMP);
976 
977         rec->AddId((HprofObjectId)obj);
978         rec->AddU4(StackTraceSerialNumber(obj));
979         rec->AddU4(length);
980         rec->AddU1(t);
981 
982         // Dump the raw, packed element values.
983         if (size == 1) {
984           rec->AddU1List((const uint8_t*)aobj->GetRawData(sizeof(uint8_t)), length);
985         } else if (size == 2) {
986           rec->AddU2List((const uint16_t*)aobj->GetRawData(sizeof(uint16_t)), length);
987         } else if (size == 4) {
988           rec->AddU4List((const uint32_t*)aobj->GetRawData(sizeof(uint32_t)), length);
989         } else if (size == 8) {
990           rec->AddU8List((const uint64_t*)aobj->GetRawData(sizeof(uint64_t)), length);
991         }
992       }
993     } else {
994       // obj is an instance object.
995       rec->AddU1(HPROF_INSTANCE_DUMP);
996       rec->AddId((HprofObjectId)obj);
997       rec->AddU4(StackTraceSerialNumber(obj));
998       rec->AddId(LookupClassId(c));
999 
1000       // Reserve some space for the length of the instance data, which we won't
1001       // know until we're done writing it.
1002       size_t size_patch_offset = rec->Size();
1003       rec->AddU4(0x77777777);
1004 
1005       // Write the instance data;  fields for this class, followed by super class fields,
1006       // and so on. Don't write the klass or monitor fields of Object.class.
1007       const mirror::Class* sclass = c;
1008       FieldHelper fh;
1009       while (!sclass->IsObjectClass()) {
1010         int ifieldCount = sclass->NumInstanceFields();
1011         for (int i = 0; i < ifieldCount; ++i) {
1012           mirror::ArtField* f = sclass->GetInstanceField(i);
1013           fh.ChangeField(f);
1014           size_t size;
1015           SignatureToBasicTypeAndSize(fh.GetTypeDescriptor(), &size);
1016           if (size == 1) {
1017             rec->AddU1(f->Get32(obj));
1018           } else if (size == 2) {
1019             rec->AddU2(f->Get32(obj));
1020           } else if (size == 4) {
1021             rec->AddU4(f->Get32(obj));
1022           } else if (size == 8) {
1023             rec->AddU8(f->Get64(obj));
1024           } else {
1025             CHECK(false);
1026           }
1027         }
1028 
1029         sclass = sclass->GetSuperClass();
1030       }
1031 
1032       // Patch the instance field length.
1033       rec->UpdateU4(size_patch_offset, rec->Size() - (size_patch_offset + 4));
1034     }
1035   }
1036 
1037   ++objects_in_segment_;
1038   return 0;
1039 }
1040 
VisitRoot(const mirror::Object * obj)1041 void Hprof::VisitRoot(const mirror::Object* obj) {
1042   uint32_t threadId = 0;  // TODO
1043   /*RootType*/ size_t type = 0;  // TODO
1044 
1045   static const HprofHeapTag xlate[] = {
1046     HPROF_ROOT_UNKNOWN,
1047     HPROF_ROOT_JNI_GLOBAL,
1048     HPROF_ROOT_JNI_LOCAL,
1049     HPROF_ROOT_JAVA_FRAME,
1050     HPROF_ROOT_NATIVE_STACK,
1051     HPROF_ROOT_STICKY_CLASS,
1052     HPROF_ROOT_THREAD_BLOCK,
1053     HPROF_ROOT_MONITOR_USED,
1054     HPROF_ROOT_THREAD_OBJECT,
1055     HPROF_ROOT_INTERNED_STRING,
1056     HPROF_ROOT_FINALIZING,
1057     HPROF_ROOT_DEBUGGER,
1058     HPROF_ROOT_REFERENCE_CLEANUP,
1059     HPROF_ROOT_VM_INTERNAL,
1060     HPROF_ROOT_JNI_MONITOR,
1061   };
1062 
1063   CHECK_LT(type, sizeof(xlate) / sizeof(HprofHeapTag));
1064   if (obj == NULL) {
1065     return;
1066   }
1067   gc_scan_state_ = xlate[type];
1068   gc_thread_serial_number_ = threadId;
1069   MarkRootObject(obj, 0);
1070   gc_scan_state_ = 0;
1071   gc_thread_serial_number_ = 0;
1072 }
1073 
1074 // If "direct_to_ddms" is true, the other arguments are ignored, and data is
1075 // sent directly to DDMS.
1076 // If "fd" is >= 0, the output will be written to that file descriptor.
1077 // Otherwise, "filename" is used to create an output file.
DumpHeap(const char * filename,int fd,bool direct_to_ddms)1078 void DumpHeap(const char* filename, int fd, bool direct_to_ddms) {
1079   CHECK(filename != NULL);
1080 
1081   Runtime::Current()->GetThreadList()->SuspendAll();
1082   Hprof hprof(filename, fd, direct_to_ddms);
1083   hprof.Dump();
1084   Runtime::Current()->GetThreadList()->ResumeAll();
1085 }
1086 
1087 }  // namespace hprof
1088 
1089 }  // namespace art
1090