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 = ¤t_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 = ¤t_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 = ¤t_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 = ¤t_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