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