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