Print this page

        

*** 63,73 **** if (_klass == Universe::constantPoolCacheKlassObj()) name = "<constantPoolCacheKlass>"; else if (_klass == Universe::compiledICHolderKlassObj()) name = "<compiledICHolderKlass>"; else name = "<no name>"; } // simplify the formatting (ILP32 vs LP64) - always cast the numbers to 64-bit ! st->print_cr("%13" FORMAT64_MODIFIER "d %13" FORMAT64_MODIFIER "u %s", (jlong) _instance_count, (julong) _instance_words * HeapWordSize, name); } --- 63,73 ---- if (_klass == Universe::constantPoolCacheKlassObj()) name = "<constantPoolCacheKlass>"; else if (_klass == Universe::compiledICHolderKlassObj()) name = "<compiledICHolderKlass>"; else name = "<no name>"; } // simplify the formatting (ILP32 vs LP64) - always cast the numbers to 64-bit ! st->print_cr(INT64_FORMAT_W(13) " " UINT64_FORMAT_W(13) " %s", (jlong) _instance_count, (julong) _instance_words * HeapWordSize, name); }
*** 78,88 **** --- 78,91 ---- return elt; } elt = elt->next(); } elt = new KlassInfoEntry(k, list()); + // We may be out of space to allocate the new entry. + if (elt != NULL) { set_list(elt); + } return elt; } void KlassInfoBucket::iterate(KlassInfoClosure* cic) { KlassInfoEntry* elt = _list;
*** 101,147 **** elt = next; } } KlassInfoTable::KlassInfoTable(int size, HeapWord* ref) { ! _size = size; _ref = ref; ! _buckets = NEW_C_HEAP_ARRAY(KlassInfoBucket, _size); ! for (int index = 0; index < _size; index++) { _buckets[index].initialize(); } } KlassInfoTable::~KlassInfoTable() { for (int index = 0; index < _size; index++) { _buckets[index].empty(); } FREE_C_HEAP_ARRAY(KlassInfoBucket, _buckets); _size = 0; } uint KlassInfoTable::hash(klassOop p) { assert(Universe::heap()->is_in_permanent((HeapWord*)p), "all klasses in permgen"); return (uint)(((uintptr_t)p - (uintptr_t)_ref) >> 2); } KlassInfoEntry* KlassInfoTable::lookup(const klassOop k) { uint idx = hash(k) % _size; KlassInfoEntry* e = _buckets[idx].lookup(k); ! assert(k == e->klass(), "must be equal"); return e; } ! void KlassInfoTable::record_instance(const oop obj) { klassOop k = obj->klass(); KlassInfoEntry* elt = lookup(k); elt->set_count(elt->count() + 1); elt->set_words(elt->words() + obj->size()); } void KlassInfoTable::iterate(KlassInfoClosure* cic) { for (int index = 0; index < _size; index++) { _buckets[index].iterate(cic); } } --- 104,167 ---- elt = next; } } KlassInfoTable::KlassInfoTable(int size, HeapWord* ref) { ! _size = 0; _ref = ref; ! _buckets = NEW_C_HEAP_ARRAY(KlassInfoBucket, size); ! if (_buckets != NULL) { ! _size = size; for (int index = 0; index < _size; index++) { _buckets[index].initialize(); } + } } KlassInfoTable::~KlassInfoTable() { + if (_buckets != NULL) { for (int index = 0; index < _size; index++) { _buckets[index].empty(); } FREE_C_HEAP_ARRAY(KlassInfoBucket, _buckets); _size = 0; + } } uint KlassInfoTable::hash(klassOop p) { assert(Universe::heap()->is_in_permanent((HeapWord*)p), "all klasses in permgen"); return (uint)(((uintptr_t)p - (uintptr_t)_ref) >> 2); } KlassInfoEntry* KlassInfoTable::lookup(const klassOop k) { uint idx = hash(k) % _size; + assert(_buckets != NULL, "Allocation failure should have been caught"); KlassInfoEntry* e = _buckets[idx].lookup(k); ! // Lookup may fail if this is a new klass for which we ! // could not allocate space for an new entry. ! assert(e == NULL || k == e->klass(), "must be equal"); return e; } ! // Return false if the entry could not be recorded on account ! // of running out of space required to create a new entry. ! bool KlassInfoTable::record_instance(const oop obj) { klassOop k = obj->klass(); KlassInfoEntry* elt = lookup(k); + // elt may be NULL if it's a new klass for which we + // could not allocate space for a new entry in the hashtable. + if (elt != NULL) { elt->set_count(elt->count() + 1); elt->set_words(elt->words() + obj->size()); + return true; + } else { + return false; + } } void KlassInfoTable::iterate(KlassInfoClosure* cic) { + assert(_size == 0 || _buckets != NULL, "Allocation failure should have been caught"); for (int index = 0; index < _size; index++) { _buckets[index].iterate(cic); } }
*** 174,184 **** st->print("%4d: ", i+1); elements()->at(i)->print_on(st); total += elements()->at(i)->count(); totalw += elements()->at(i)->words(); } ! st->print_cr("Total %13" FORMAT64_MODIFIER "d %13" FORMAT64_MODIFIER "u", total, totalw * HeapWordSize); } void KlassInfoHisto::print_on(outputStream* st) const { st->print_cr("%s",title()); --- 194,204 ---- st->print("%4d: ", i+1); elements()->at(i)->print_on(st); total += elements()->at(i)->count(); totalw += elements()->at(i)->words(); } ! st->print_cr("Total " INT64_FORMAT_W(13) " " UINT64_FORMAT_W(13), total, totalw * HeapWordSize); } void KlassInfoHisto::print_on(outputStream* st) const { st->print_cr("%s",title());
*** 197,212 **** }; class RecordInstanceClosure : public ObjectClosure { private: KlassInfoTable* _cit; public: ! RecordInstanceClosure(KlassInfoTable* cit) : _cit(cit) {} void do_object(oop obj) { ! _cit->record_instance(obj); } }; void HeapInspection::heap_inspection(outputStream* st) { ResourceMark rm; HeapWord* ref; --- 217,238 ---- }; class RecordInstanceClosure : public ObjectClosure { private: KlassInfoTable* _cit; + size_t _missed_count; public: ! RecordInstanceClosure(KlassInfoTable* cit) : ! _cit(cit), _missed_count(0) {} void do_object(oop obj) { ! if (!_cit->record_instance(obj)) { ! _missed_count++; } + } + + size_t missed_count() { return _missed_count; } }; void HeapInspection::heap_inspection(outputStream* st) { ResourceMark rm; HeapWord* ref;
*** 228,252 **** #endif // SERIALGC default: ShouldNotReachHere(); // Unexpected heap kind for this op } // Collect klass instance info - - // Iterate over objects in the heap KlassInfoTable cit(KlassInfoTable::cit_size, ref); RecordInstanceClosure ric(&cit); Universe::heap()->object_iterate(&ric); // Sort and print klass instance info KlassInfoHisto histo("\n" " num #instances #bytes class name\n" "----------------------------------------------", KlassInfoHisto::histo_initial_size); HistoClosure hc(&histo); cit.iterate(&hc); histo.sort(); histo.print_on(st); st->flush(); if (Universe::heap()->kind() == CollectedHeap::GenCollectedHeap) { GenCollectedHeap* gch = GenCollectedHeap::heap(); gch->gc_epilogue(false /* !full */); // release all acquired locks --- 254,288 ---- #endif // SERIALGC default: ShouldNotReachHere(); // Unexpected heap kind for this op } // Collect klass instance info KlassInfoTable cit(KlassInfoTable::cit_size, ref); + if (!cit.allocation_failed()) { + // Iterate over objects in the heap RecordInstanceClosure ric(&cit); Universe::heap()->object_iterate(&ric); + // Report if certain classes are not counted because of + // running out of C-heap for the histogram. + size_t missed_count = ric.missed_count(); + if (missed_count != 0) { + st->print_cr("WARNING: Ran out of C-heap; undercounted " SIZE_FORMAT " instances in data below", + missed_count); + } // Sort and print klass instance info KlassInfoHisto histo("\n" " num #instances #bytes class name\n" "----------------------------------------------", KlassInfoHisto::histo_initial_size); HistoClosure hc(&histo); cit.iterate(&hc); histo.sort(); histo.print_on(st); + } else { + st->print_cr("WARNING: Ran out of C-heap; histogram not generated"); + } st->flush(); if (Universe::heap()->kind() == CollectedHeap::GenCollectedHeap) { GenCollectedHeap* gch = GenCollectedHeap::heap(); gch->gc_epilogue(false /* !full */); // release all acquired locks