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