src/share/vm/memory/heapInspection.cpp
Print this page
rev 4773 : 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>
*** 93,103 ****
if (elt->is_equal(k)) {
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;
--- 93,103 ----
if (elt->is_equal(k)) {
return elt;
}
elt = elt->next();
}
! elt = new (std::nothrow) KlassInfoEntry(k, list());
// We may be out of space to allocate the new entry.
if (elt != NULL) {
set_list(elt);
}
return elt;
*** 125,141 ****
// This has the SIDE EFFECT of creating a KlassInfoEntry
// for <k>, if one doesn't exist yet.
_table->lookup(k);
}
! KlassInfoTable::KlassInfoTable(int size, HeapWord* ref,
! bool need_class_stats) {
_size = 0;
! _ref = ref;
! _buckets = NEW_C_HEAP_ARRAY(KlassInfoBucket, size, mtInternal);
if (_buckets != NULL) {
! _size = size;
for (int index = 0; index < _size; index++) {
_buckets[index].initialize();
}
if (need_class_stats) {
AllClassesFinder finder(this);
--- 125,143 ----
// This has the SIDE EFFECT of creating a KlassInfoEntry
// for <k>, if one doesn't exist yet.
_table->lookup(k);
}
! KlassInfoTable::KlassInfoTable(bool need_class_stats) {
! _size_of_instances_in_words = 0;
_size = 0;
! _ref = (HeapWord*) Universe::boolArrayKlassObj();
! _buckets =
! (KlassInfoBucket*) AllocateHeap(sizeof(KlassInfoBucket) * _num_buckets,
! mtInternal, 0, AllocFailStrategy::RETURN_NULL);
if (_buckets != NULL) {
! _size = _num_buckets;
for (int index = 0; index < _size; index++) {
_buckets[index].initialize();
}
if (need_class_stats) {
AllClassesFinder finder(this);
*** 177,186 ****
--- 179,189 ----
// 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());
+ _size_of_instances_in_words += obj->size();
return true;
} else {
return false;
}
}
*** 190,207 ****
for (int index = 0; index < _size; index++) {
_buckets[index].iterate(cic);
}
}
int KlassInfoHisto::sort_helper(KlassInfoEntry** e1, KlassInfoEntry** e2) {
return (*e1)->compare(*e1,*e2);
}
! KlassInfoHisto::KlassInfoHisto(KlassInfoTable* cit, const char* title, int estimatedCount) :
_cit(cit),
_title(title) {
! _elements = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<KlassInfoEntry*>(estimatedCount,true);
}
KlassInfoHisto::~KlassInfoHisto() {
delete _elements;
}
--- 193,214 ----
for (int index = 0; index < _size; index++) {
_buckets[index].iterate(cic);
}
}
+ size_t KlassInfoTable::size_of_instances_in_words() const {
+ return _size_of_instances_in_words;
+ }
+
int KlassInfoHisto::sort_helper(KlassInfoEntry** e1, KlassInfoEntry** e2) {
return (*e1)->compare(*e1,*e2);
}
! KlassInfoHisto::KlassInfoHisto(KlassInfoTable* cit, const char* title) :
_cit(cit),
_title(title) {
! _elements = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<KlassInfoEntry*>(_histo_initial_size, true);
}
KlassInfoHisto::~KlassInfoHisto() {
delete _elements;
}
*** 442,470 ****
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, bool need_prologue) {
ResourceMark rm;
- // Get some random number for ref (the hash key)
- HeapWord* ref = (HeapWord*) Universe::boolArrayKlassObj();
- CollectedHeap* heap = Universe::heap();
- bool is_shared_heap = false;
if (_print_help) {
for (int c=0; c<KlassSizeStats::_num_columns; c++) {
st->print("%s:\n\t", name_table[c]);
const int max_col = 60;
--- 449,489 ----
class RecordInstanceClosure : public ObjectClosure {
private:
KlassInfoTable* _cit;
size_t _missed_count;
+ BoolObjectClosure* _filter;
public:
! RecordInstanceClosure(KlassInfoTable* cit, BoolObjectClosure* filter) :
! _cit(cit), _missed_count(0), _filter(filter) {}
void do_object(oop obj) {
+ if (should_visit(obj)) {
if (!_cit->record_instance(obj)) {
_missed_count++;
}
}
+ }
size_t missed_count() { return _missed_count; }
+
+ private:
+ bool should_visit(oop obj) {
+ return _filter == NULL || _filter->do_object_b(obj);
+ }
};
! size_t HeapInspection::populate_table(KlassInfoTable* cit, BoolObjectClosure *filter) {
! ResourceMark rm;
!
! RecordInstanceClosure ric(cit, filter);
! Universe::heap()->object_iterate(&ric);
! return ric.missed_count();
! }
!
! void HeapInspection::heap_inspection(outputStream* st) {
ResourceMark rm;
if (_print_help) {
for (int c=0; c<KlassSizeStats::_num_columns; c++) {
st->print("%s:\n\t", name_table[c]);
const int max_col = 60;
*** 480,522 ****
st->print_cr(".\n");
}
return;
}
! // Collect klass instance info
! KlassInfoTable cit(KlassInfoTable::cit_size, ref, _print_class_stats);
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
" total instances in data below",
missed_count);
}
// Sort and print klass instance info
const char *title = "\n"
" num #instances #bytes class name\n"
"----------------------------------------------";
! KlassInfoHisto histo(&cit, title, KlassInfoHisto::histo_initial_size);
HistoClosure hc(&histo);
cit.iterate(&hc);
histo.sort();
histo.print_histo_on(st, _print_class_stats, _csv_format, _columns);
} else {
st->print_cr("WARNING: Ran out of C-heap; histogram not generated");
}
st->flush();
-
- if (need_prologue && is_shared_heap) {
- SharedHeap* sh = (SharedHeap*)heap;
- sh->gc_epilogue(false /* !full */); // release all acquired locks, etc.
- }
}
class FindInstanceClosure : public ObjectClosure {
private:
Klass* _klass;
--- 499,532 ----
st->print_cr(".\n");
}
return;
}
! KlassInfoTable cit(_print_class_stats);
if (!cit.allocation_failed()) {
! size_t missed_count = populate_table(&cit);
if (missed_count != 0) {
st->print_cr("WARNING: Ran out of C-heap; undercounted " SIZE_FORMAT
" total instances in data below",
missed_count);
}
+
// Sort and print klass instance info
const char *title = "\n"
" num #instances #bytes class name\n"
"----------------------------------------------";
! KlassInfoHisto histo(&cit, title);
HistoClosure hc(&histo);
+
cit.iterate(&hc);
+
histo.sort();
histo.print_histo_on(st, _print_class_stats, _csv_format, _columns);
} else {
st->print_cr("WARNING: Ran out of C-heap; histogram not generated");
}
st->flush();
}
class FindInstanceClosure : public ObjectClosure {
private:
Klass* _klass;