Home | History | Annotate | Download | only in hprof
      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:
    186   HprofRecord() {
    187     dirty_ = false;
    188     alloc_length_ = 128;
    189     body_ = reinterpret_cast<unsigned char*>(malloc(alloc_length_));
    190     fp_ = NULL;
    191   }
    192 
    193   ~HprofRecord() {
    194     free(body_);
    195   }
    196 
    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 
    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 
    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 
    244   int AddU2(uint16_t value) {
    245     return AddU2List(&value, 1);
    246   }
    247 
    248   int AddU4(uint32_t value) {
    249     return AddU4List(&value, 1);
    250   }
    251 
    252   int AddU8(uint64_t value) {
    253     return AddU8List(&value, 1);
    254   }
    255 
    256   int AddId(HprofObjectId value) {
    257     return AddU4((uint32_t) value);
    258   }
    259 
    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 
    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 
    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 
    301   void UpdateU4(size_t offset, uint32_t new_value) {
    302     U4_TO_BUF_BE(body_, offset, new_value);
    303   }
    304 
    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 
    320   int AddIdList(const HprofObjectId* values, size_t numValues) {
    321     return AddU4List((const uint32_t*) values, numValues);
    322   }
    323 
    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 
    329   size_t Size() const {
    330     return length_;
    331   }
    332 
    333  private:
    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:
    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 
    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 
    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:
    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 
    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 
    506   void Finish() {
    507   }
    508 
    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 
    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 
    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 
    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 
    593   HprofStringId LookupStringId(mirror::String* string) {
    594     return LookupStringId(string->ToModifiedUtf8());
    595   }
    596 
    597   HprofStringId LookupStringId(const char* string) {
    598     return LookupStringId(std::string(string));
    599   }
    600 
    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 
    611   HprofStringId LookupClassNameId(const mirror::Class* c)
    612       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    613     return LookupStringId(PrettyDescriptor(c));
    614   }
    615 
    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 
    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 
    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 
    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.
    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 
    830 static int StackTraceSerialNumber(const mirror::Object* /*obj*/) {
    831   return HPROF_NULL_STACK_TRACE;
    832 }
    833 
    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 
   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.
   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