comparison src/share/vm/memory/heapInspection.cpp @ 10405:f2110083203d

8005849: JEP 167: Event-Based JVM Tracing Reviewed-by: acorn, coleenp, sla Contributed-by: Karen Kinnear <karen.kinnear@oracle.com>, Bengt Rutisson <bengt.rutisson@oracle.com>, Calvin Cheung <calvin.cheung@oracle.com>, Erik Gahlin <erik.gahlin@oracle.com>, Erik Helin <erik.helin@oracle.com>, Jesper Wilhelmsson <jesper.wilhelmsson@oracle.com>, Keith McGuigan <keith.mcguigan@oracle.com>, Mattias Tobiasson <mattias.tobiasson@oracle.com>, Markus Gronlund <markus.gronlund@oracle.com>, Mikael Auno <mikael.auno@oracle.com>, Nils Eliasson <nils.eliasson@oracle.com>, Nils Loodin <nils.loodin@oracle.com>, Rickard Backman <rickard.backman@oracle.com>, Staffan Larsen <staffan.larsen@oracle.com>, Stefan Karlsson <stefan.karlsson@oracle.com>, Yekaterina Kantserova <yekaterina.kantserova@oracle.com>
author sla
date Mon, 10 Jun 2013 11:30:51 +0200
parents 92ef81e2f571
children e0c9a1d29eb4
comparison
equal deleted inserted replaced
10404:d0add7016434 10405:f2110083203d
93 if (elt->is_equal(k)) { 93 if (elt->is_equal(k)) {
94 return elt; 94 return elt;
95 } 95 }
96 elt = elt->next(); 96 elt = elt->next();
97 } 97 }
98 elt = new KlassInfoEntry(k, list()); 98 elt = new (std::nothrow) KlassInfoEntry(k, list());
99 // We may be out of space to allocate the new entry. 99 // We may be out of space to allocate the new entry.
100 if (elt != NULL) { 100 if (elt != NULL) {
101 set_list(elt); 101 set_list(elt);
102 } 102 }
103 return elt; 103 return elt;
125 // This has the SIDE EFFECT of creating a KlassInfoEntry 125 // This has the SIDE EFFECT of creating a KlassInfoEntry
126 // for <k>, if one doesn't exist yet. 126 // for <k>, if one doesn't exist yet.
127 _table->lookup(k); 127 _table->lookup(k);
128 } 128 }
129 129
130 KlassInfoTable::KlassInfoTable(int size, HeapWord* ref, 130 KlassInfoTable::KlassInfoTable(bool need_class_stats) {
131 bool need_class_stats) { 131 _size_of_instances_in_words = 0;
132 _size = 0; 132 _size = 0;
133 _ref = ref; 133 _ref = (HeapWord*) Universe::boolArrayKlassObj();
134 _buckets = NEW_C_HEAP_ARRAY(KlassInfoBucket, size, mtInternal); 134 _buckets =
135 (KlassInfoBucket*) AllocateHeap(sizeof(KlassInfoBucket) * _num_buckets,
136 mtInternal, 0, AllocFailStrategy::RETURN_NULL);
135 if (_buckets != NULL) { 137 if (_buckets != NULL) {
136 _size = size; 138 _size = _num_buckets;
137 for (int index = 0; index < _size; index++) { 139 for (int index = 0; index < _size; index++) {
138 _buckets[index].initialize(); 140 _buckets[index].initialize();
139 } 141 }
140 if (need_class_stats) { 142 if (need_class_stats) {
141 AllClassesFinder finder(this); 143 AllClassesFinder finder(this);
177 // elt may be NULL if it's a new klass for which we 179 // elt may be NULL if it's a new klass for which we
178 // could not allocate space for a new entry in the hashtable. 180 // could not allocate space for a new entry in the hashtable.
179 if (elt != NULL) { 181 if (elt != NULL) {
180 elt->set_count(elt->count() + 1); 182 elt->set_count(elt->count() + 1);
181 elt->set_words(elt->words() + obj->size()); 183 elt->set_words(elt->words() + obj->size());
184 _size_of_instances_in_words += obj->size();
182 return true; 185 return true;
183 } else { 186 } else {
184 return false; 187 return false;
185 } 188 }
186 } 189 }
190 for (int index = 0; index < _size; index++) { 193 for (int index = 0; index < _size; index++) {
191 _buckets[index].iterate(cic); 194 _buckets[index].iterate(cic);
192 } 195 }
193 } 196 }
194 197
198 size_t KlassInfoTable::size_of_instances_in_words() const {
199 return _size_of_instances_in_words;
200 }
201
195 int KlassInfoHisto::sort_helper(KlassInfoEntry** e1, KlassInfoEntry** e2) { 202 int KlassInfoHisto::sort_helper(KlassInfoEntry** e1, KlassInfoEntry** e2) {
196 return (*e1)->compare(*e1,*e2); 203 return (*e1)->compare(*e1,*e2);
197 } 204 }
198 205
199 KlassInfoHisto::KlassInfoHisto(KlassInfoTable* cit, const char* title, int estimatedCount) : 206 KlassInfoHisto::KlassInfoHisto(KlassInfoTable* cit, const char* title) :
200 _cit(cit), 207 _cit(cit),
201 _title(title) { 208 _title(title) {
202 _elements = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<KlassInfoEntry*>(estimatedCount,true); 209 _elements = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<KlassInfoEntry*>(_histo_initial_size, true);
203 } 210 }
204 211
205 KlassInfoHisto::~KlassInfoHisto() { 212 KlassInfoHisto::~KlassInfoHisto() {
206 delete _elements; 213 delete _elements;
207 } 214 }
442 449
443 class RecordInstanceClosure : public ObjectClosure { 450 class RecordInstanceClosure : public ObjectClosure {
444 private: 451 private:
445 KlassInfoTable* _cit; 452 KlassInfoTable* _cit;
446 size_t _missed_count; 453 size_t _missed_count;
454 BoolObjectClosure* _filter;
447 public: 455 public:
448 RecordInstanceClosure(KlassInfoTable* cit) : 456 RecordInstanceClosure(KlassInfoTable* cit, BoolObjectClosure* filter) :
449 _cit(cit), _missed_count(0) {} 457 _cit(cit), _missed_count(0), _filter(filter) {}
450 458
451 void do_object(oop obj) { 459 void do_object(oop obj) {
452 if (!_cit->record_instance(obj)) { 460 if (should_visit(obj)) {
453 _missed_count++; 461 if (!_cit->record_instance(obj)) {
462 _missed_count++;
463 }
454 } 464 }
455 } 465 }
456 466
457 size_t missed_count() { return _missed_count; } 467 size_t missed_count() { return _missed_count; }
468
469 private:
470 bool should_visit(oop obj) {
471 return _filter == NULL || _filter->do_object_b(obj);
472 }
458 }; 473 };
459 474
460 void HeapInspection::heap_inspection(outputStream* st, bool need_prologue) { 475 size_t HeapInspection::populate_table(KlassInfoTable* cit, BoolObjectClosure *filter) {
461 ResourceMark rm; 476 ResourceMark rm;
462 // Get some random number for ref (the hash key) 477
463 HeapWord* ref = (HeapWord*) Universe::boolArrayKlassObj(); 478 RecordInstanceClosure ric(cit, filter);
464 CollectedHeap* heap = Universe::heap(); 479 Universe::heap()->object_iterate(&ric);
465 bool is_shared_heap = false; 480 return ric.missed_count();
481 }
482
483 void HeapInspection::heap_inspection(outputStream* st) {
484 ResourceMark rm;
466 485
467 if (_print_help) { 486 if (_print_help) {
468 for (int c=0; c<KlassSizeStats::_num_columns; c++) { 487 for (int c=0; c<KlassSizeStats::_num_columns; c++) {
469 st->print("%s:\n\t", name_table[c]); 488 st->print("%s:\n\t", name_table[c]);
470 const int max_col = 60; 489 const int max_col = 60;
480 st->print_cr(".\n"); 499 st->print_cr(".\n");
481 } 500 }
482 return; 501 return;
483 } 502 }
484 503
485 // Collect klass instance info 504 KlassInfoTable cit(_print_class_stats);
486 KlassInfoTable cit(KlassInfoTable::cit_size, ref, _print_class_stats);
487 if (!cit.allocation_failed()) { 505 if (!cit.allocation_failed()) {
488 // Iterate over objects in the heap 506 size_t missed_count = populate_table(&cit);
489 RecordInstanceClosure ric(&cit);
490 Universe::heap()->object_iterate(&ric);
491
492 // Report if certain classes are not counted because of
493 // running out of C-heap for the histogram.
494 size_t missed_count = ric.missed_count();
495 if (missed_count != 0) { 507 if (missed_count != 0) {
496 st->print_cr("WARNING: Ran out of C-heap; undercounted " SIZE_FORMAT 508 st->print_cr("WARNING: Ran out of C-heap; undercounted " SIZE_FORMAT
497 " total instances in data below", 509 " total instances in data below",
498 missed_count); 510 missed_count);
499 } 511 }
512
500 // Sort and print klass instance info 513 // Sort and print klass instance info
501 const char *title = "\n" 514 const char *title = "\n"
502 " num #instances #bytes class name\n" 515 " num #instances #bytes class name\n"
503 "----------------------------------------------"; 516 "----------------------------------------------";
504 KlassInfoHisto histo(&cit, title, KlassInfoHisto::histo_initial_size); 517 KlassInfoHisto histo(&cit, title);
505 HistoClosure hc(&histo); 518 HistoClosure hc(&histo);
519
506 cit.iterate(&hc); 520 cit.iterate(&hc);
521
507 histo.sort(); 522 histo.sort();
508 histo.print_histo_on(st, _print_class_stats, _csv_format, _columns); 523 histo.print_histo_on(st, _print_class_stats, _csv_format, _columns);
509 } else { 524 } else {
510 st->print_cr("WARNING: Ran out of C-heap; histogram not generated"); 525 st->print_cr("WARNING: Ran out of C-heap; histogram not generated");
511 } 526 }
512 st->flush(); 527 st->flush();
513
514 if (need_prologue && is_shared_heap) {
515 SharedHeap* sh = (SharedHeap*)heap;
516 sh->gc_epilogue(false /* !full */); // release all acquired locks, etc.
517 }
518 } 528 }
519 529
520 class FindInstanceClosure : public ObjectClosure { 530 class FindInstanceClosure : public ObjectClosure {
521 private: 531 private:
522 Klass* _klass; 532 Klass* _klass;