hprof.cc revision ccc68d692c5d6ad54cb74163b8930182f9c87d3c
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 61namespace art { 62 63namespace 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 106enum 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: 124enum 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 152enum HprofHeapId { 153 HPROF_HEAP_DEFAULT = 0, 154 HPROF_HEAP_ZYGOTE = 'Z', 155 HPROF_HEAP_APP = 'A' 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 = ¤t_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 = ¤t_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 = ¤t_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 = ¤t_record_; 850 HprofHeapId desiredHeap = false ? HPROF_HEAP_ZYGOTE : HPROF_HEAP_APP; // TODO: zygote objects? 851 852 if (objects_in_segment_ >= OBJECTS_PER_SEGMENT || rec->Size() >= BYTES_PER_SEGMENT) { 853 StartNewHeapDumpSegment(); 854 } 855 856 if (desiredHeap != current_heap_) { 857 HprofStringId nameId; 858 859 // This object is in a different heap than the current one. 860 // Emit a HEAP_DUMP_INFO tag to change heaps. 861 rec->AddU1(HPROF_HEAP_DUMP_INFO); 862 rec->AddU4((uint32_t)desiredHeap); // uint32_t: heap id 863 switch (desiredHeap) { 864 case HPROF_HEAP_APP: 865 nameId = LookupStringId("app"); 866 break; 867 case HPROF_HEAP_ZYGOTE: 868 nameId = LookupStringId("zygote"); 869 break; 870 default: 871 // Internal error 872 LOG(ERROR) << "Unexpected desiredHeap"; 873 nameId = LookupStringId("<ILLEGAL>"); 874 break; 875 } 876 rec->AddStringId(nameId); 877 current_heap_ = desiredHeap; 878 } 879 880 mirror::Class* c = obj->GetClass(); 881 if (c == NULL) { 882 // This object will bother HprofReader, because it has a NULL 883 // class, so just don't dump it. It could be 884 // gDvm.unlinkedJavaLangClass or it could be an object just 885 // allocated which hasn't been initialized yet. 886 } else { 887 if (obj->IsClass()) { 888 mirror::Class* thisClass = obj->AsClass(); 889 // obj is a ClassObject. 890 size_t sFieldCount = thisClass->NumStaticFields(); 891 if (sFieldCount != 0) { 892 int byteLength = sFieldCount * sizeof(JValue); // TODO bogus; fields are packed 893 // Create a byte array to reflect the allocation of the 894 // StaticField array at the end of this class. 895 rec->AddU1(HPROF_PRIMITIVE_ARRAY_DUMP); 896 rec->AddClassStaticsId(thisClass); 897 rec->AddU4(StackTraceSerialNumber(obj)); 898 rec->AddU4(byteLength); 899 rec->AddU1(hprof_basic_byte); 900 for (int i = 0; i < byteLength; ++i) { 901 rec->AddU1(0); 902 } 903 } 904 905 rec->AddU1(HPROF_CLASS_DUMP); 906 rec->AddClassId(LookupClassId(thisClass)); 907 rec->AddU4(StackTraceSerialNumber(thisClass)); 908 rec->AddClassId(LookupClassId(thisClass->GetSuperClass())); 909 rec->AddObjectId(thisClass->GetClassLoader()); 910 rec->AddObjectId(nullptr); // no signer 911 rec->AddObjectId(nullptr); // no prot domain 912 rec->AddObjectId(nullptr); // reserved 913 rec->AddObjectId(nullptr); // reserved 914 if (thisClass->IsClassClass()) { 915 // ClassObjects have their static fields appended, so aren't all the same size. 916 // But they're at least this size. 917 rec->AddU4(sizeof(mirror::Class)); // instance size 918 } else if (thisClass->IsArrayClass() || thisClass->IsPrimitive()) { 919 rec->AddU4(0); 920 } else { 921 rec->AddU4(thisClass->GetObjectSize()); // instance size 922 } 923 924 rec->AddU2(0); // empty const pool 925 926 // Static fields 927 if (sFieldCount == 0) { 928 rec->AddU2((uint16_t)0); 929 } else { 930 rec->AddU2((uint16_t)(sFieldCount+1)); 931 rec->AddStringId(LookupStringId(STATIC_OVERHEAD_NAME)); 932 rec->AddU1(hprof_basic_object); 933 rec->AddClassStaticsId(thisClass); 934 935 for (size_t i = 0; i < sFieldCount; ++i) { 936 mirror::ArtField* f = thisClass->GetStaticField(i); 937 938 size_t size; 939 HprofBasicType t = SignatureToBasicTypeAndSize(f->GetTypeDescriptor(), &size); 940 rec->AddStringId(LookupStringId(f->GetName())); 941 rec->AddU1(t); 942 if (size == 1) { 943 rec->AddU1(static_cast<uint8_t>(f->Get32(thisClass))); 944 } else if (size == 2) { 945 rec->AddU2(static_cast<uint16_t>(f->Get32(thisClass))); 946 } else if (size == 4) { 947 rec->AddU4(f->Get32(thisClass)); 948 } else if (size == 8) { 949 rec->AddU8(f->Get64(thisClass)); 950 } else { 951 CHECK(false); 952 } 953 } 954 } 955 956 // Instance fields for this class (no superclass fields) 957 int iFieldCount = thisClass->IsObjectClass() ? 0 : thisClass->NumInstanceFields(); 958 rec->AddU2((uint16_t)iFieldCount); 959 for (int i = 0; i < iFieldCount; ++i) { 960 mirror::ArtField* f = thisClass->GetInstanceField(i); 961 HprofBasicType t = SignatureToBasicTypeAndSize(f->GetTypeDescriptor(), NULL); 962 rec->AddStringId(LookupStringId(f->GetName())); 963 rec->AddU1(t); 964 } 965 } else if (c->IsArrayClass()) { 966 mirror::Array* aobj = obj->AsArray(); 967 uint32_t length = aobj->GetLength(); 968 969 if (obj->IsObjectArray()) { 970 // obj is an object array. 971 rec->AddU1(HPROF_OBJECT_ARRAY_DUMP); 972 973 rec->AddObjectId(obj); 974 rec->AddU4(StackTraceSerialNumber(obj)); 975 rec->AddU4(length); 976 rec->AddClassId(LookupClassId(c)); 977 978 // Dump the elements, which are always objects or NULL. 979 rec->AddIdList(aobj->AsObjectArray<mirror::Object>()); 980 } else { 981 size_t size; 982 HprofBasicType t = PrimitiveToBasicTypeAndSize(c->GetComponentType()->GetPrimitiveType(), &size); 983 984 // obj is a primitive array. 985 rec->AddU1(HPROF_PRIMITIVE_ARRAY_DUMP); 986 987 rec->AddObjectId(obj); 988 rec->AddU4(StackTraceSerialNumber(obj)); 989 rec->AddU4(length); 990 rec->AddU1(t); 991 992 // Dump the raw, packed element values. 993 if (size == 1) { 994 rec->AddU1List((const uint8_t*)aobj->GetRawData(sizeof(uint8_t), 0), length); 995 } else if (size == 2) { 996 rec->AddU2List((const uint16_t*)aobj->GetRawData(sizeof(uint16_t), 0), length); 997 } else if (size == 4) { 998 rec->AddU4List((const uint32_t*)aobj->GetRawData(sizeof(uint32_t), 0), length); 999 } else if (size == 8) { 1000 rec->AddU8List((const uint64_t*)aobj->GetRawData(sizeof(uint64_t), 0), length); 1001 } 1002 } 1003 } else { 1004 // obj is an instance object. 1005 rec->AddU1(HPROF_INSTANCE_DUMP); 1006 rec->AddObjectId(obj); 1007 rec->AddU4(StackTraceSerialNumber(obj)); 1008 rec->AddClassId(LookupClassId(c)); 1009 1010 // Reserve some space for the length of the instance data, which we won't 1011 // know until we're done writing it. 1012 size_t size_patch_offset = rec->Size(); 1013 rec->AddU4(0x77777777); 1014 1015 // Write the instance data; fields for this class, followed by super class fields, 1016 // and so on. Don't write the klass or monitor fields of Object.class. 1017 mirror::Class* sclass = c; 1018 while (!sclass->IsObjectClass()) { 1019 int ifieldCount = sclass->NumInstanceFields(); 1020 for (int i = 0; i < ifieldCount; ++i) { 1021 mirror::ArtField* f = sclass->GetInstanceField(i); 1022 size_t size; 1023 SignatureToBasicTypeAndSize(f->GetTypeDescriptor(), &size); 1024 if (size == 1) { 1025 rec->AddU1(f->Get32(obj)); 1026 } else if (size == 2) { 1027 rec->AddU2(f->Get32(obj)); 1028 } else if (size == 4) { 1029 rec->AddU4(f->Get32(obj)); 1030 } else { 1031 CHECK_EQ(size, 8U); 1032 rec->AddU8(f->Get64(obj)); 1033 } 1034 } 1035 1036 sclass = sclass->GetSuperClass(); 1037 } 1038 1039 // Patch the instance field length. 1040 rec->UpdateU4(size_patch_offset, rec->Size() - (size_patch_offset + 4)); 1041 } 1042 } 1043 1044 ++objects_in_segment_; 1045 return 0; 1046} 1047 1048void Hprof::VisitRoot(const mirror::Object* obj, uint32_t thread_id, RootType type) { 1049 static const HprofHeapTag xlate[] = { 1050 HPROF_ROOT_UNKNOWN, 1051 HPROF_ROOT_JNI_GLOBAL, 1052 HPROF_ROOT_JNI_LOCAL, 1053 HPROF_ROOT_JAVA_FRAME, 1054 HPROF_ROOT_NATIVE_STACK, 1055 HPROF_ROOT_STICKY_CLASS, 1056 HPROF_ROOT_THREAD_BLOCK, 1057 HPROF_ROOT_MONITOR_USED, 1058 HPROF_ROOT_THREAD_OBJECT, 1059 HPROF_ROOT_INTERNED_STRING, 1060 HPROF_ROOT_FINALIZING, 1061 HPROF_ROOT_DEBUGGER, 1062 HPROF_ROOT_REFERENCE_CLEANUP, 1063 HPROF_ROOT_VM_INTERNAL, 1064 HPROF_ROOT_JNI_MONITOR, 1065 }; 1066 CHECK_LT(type, sizeof(xlate) / sizeof(HprofHeapTag)); 1067 if (obj == NULL) { 1068 return; 1069 } 1070 gc_scan_state_ = xlate[type]; 1071 gc_thread_serial_number_ = thread_id; 1072 MarkRootObject(obj, 0); 1073 gc_scan_state_ = 0; 1074 gc_thread_serial_number_ = 0; 1075} 1076 1077// If "direct_to_ddms" is true, the other arguments are ignored, and data is 1078// sent directly to DDMS. 1079// If "fd" is >= 0, the output will be written to that file descriptor. 1080// Otherwise, "filename" is used to create an output file. 1081void DumpHeap(const char* filename, int fd, bool direct_to_ddms) { 1082 CHECK(filename != NULL); 1083 1084 Runtime::Current()->GetThreadList()->SuspendAll(); 1085 Hprof hprof(filename, fd, direct_to_ddms); 1086 hprof.Dump(); 1087 Runtime::Current()->GetThreadList()->ResumeAll(); 1088} 1089 1090} // namespace hprof 1091 1092} // namespace art 1093