src/share/vm/memory/heapInspection.cpp

Print this page

        

*** 1,7 **** /* ! * Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. --- 1,7 ---- /* ! * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation.
*** 127,137 **** // 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, --- 127,137 ---- // This has the SIDE EFFECT of creating a KlassInfoEntry // for <k>, if one doesn't exist yet. _table->lookup(k); } ! KlassInfoTable::KlassInfoTable(bool add_all_classes) { _size_of_instances_in_words = 0; _size = 0; _ref = (HeapWord*) Universe::boolArrayKlassObj(); _buckets = (KlassInfoBucket*) AllocateHeap(sizeof(KlassInfoBucket) * _num_buckets,
*** 139,149 **** if (_buckets != NULL) { _size = _num_buckets; for (int index = 0; index < _size; index++) { _buckets[index].initialize(); } ! if (need_class_stats) { AllClassesFinder finder(this); ClassLoaderDataGraph::classes_do(&finder); } } } --- 139,149 ---- if (_buckets != NULL) { _size = _num_buckets; for (int index = 0; index < _size; index++) { _buckets[index].initialize(); } ! if (add_all_classes) { AllClassesFinder finder(this); ClassLoaderDataGraph::classes_do(&finder); } } }
*** 297,306 **** --- 297,419 ---- st->print(",ClassLoader"); } st->cr(); } + class HierarchyClosure : public KlassInfoClosure { + private: + GrowableArray<KlassInfoEntry*> *_elements; + public: + HierarchyClosure(GrowableArray<KlassInfoEntry*> *_elements) : _elements(_elements) {} + + void do_cinfo(KlassInfoEntry* cie) { + // ignore array classes + if (cie->klass()->oop_is_instance()) { + _elements->append(cie); + } + } + }; + + void KlassHierarchy::print_class_hierarchy(outputStream* st) { + ResourceMark rm; + int i; + Stack <KlassInfoEntry*, mtClass> class_stack; + Stack <KlassInfoEntry*, mtClass> super_stack; + GrowableArray<KlassInfoEntry*> elements; + + // Add all classes to the KlassInfoTable, which allows for quick lookup. + // A KlassInfoEntry will be created for each class. + KlassInfoTable cit(true); + if (cit.allocation_failed()) { + st->print_cr("WARNING: Ran out of C-heap; hierarchy not generated"); + return; + } + + // Add all created KlassInfoEntry instances to the elements array for easy + // iteration, and to allow each KlassInfoEntry instance to have a unique index. + HierarchyClosure hc(&elements); + cit.iterate(&hc); + + // Set the index for each class + for(i=0; i < elements.length(); i++) { + elements.at(i)->set_index(i+1); + } + + // Iterate over all the classes, adding each class to the subclass array of + // its superclass. + for(i=0; i < elements.length(); i++) { + KlassInfoEntry* e = (KlassInfoEntry*)elements.at(i); + const Klass* k = e->klass(); + Klass* super = ((InstanceKlass*)k)->java_super(); + if (super != NULL) { + KlassInfoEntry* super_e = cit.lookup(super); + assert(super_e != NULL, "could not lookup superclass"); + e->set_super_index(super_e->index()); + super_e->add_subclass(e); + } + } + + // Now we do a depth first traversal of the class hierachry. The class_stack will + // maintain the list of classes we still need to process. Start things off + // by priming it with java.lang.Object. + KlassInfoEntry* jlo_cie = cit.lookup(SystemDictionary::Object_klass()); + assert(jlo_cie != NULL, "could not lookup java.lang.Object"); + class_stack.push(jlo_cie); + + // Repeatedly pop the top item off the stack, print its class info, + // and push all of its subclasses on to the stack. Do this until there + // are no classes left on the stack. + // + // We also keep track of the stack of superclasses so we know + // all the current superclasses for the current class. This is how + // we determine the proper indentation when printing the class. + long curr_super_index = -1; + while (!class_stack.is_empty()) { + KlassInfoEntry* curr_cie = class_stack.pop(); + + // Make sure super_stack is current with the class we just popped. + while (curr_cie->super_index() != curr_super_index) { + assert(!super_stack.is_empty(), "super_stack should not be empty"); + curr_super_index = super_stack.pop()->super_index(); + } + + print_class(st, curr_cie, &super_stack); + + if (curr_cie->subclasses() != NULL) { + // Current class has subclasses, so push all of them onto the stack + for (int i = 0; i < curr_cie->subclasses()->length(); i++) { + class_stack.push(curr_cie->subclasses()->at(i)); + } + // Add current class to superclass stack. + super_stack.push(curr_cie); + curr_super_index = curr_cie->index(); + } + } + + st->flush(); + } + + void KlassHierarchy::print_class(outputStream* st, KlassInfoEntry* cie, + Stack <KlassInfoEntry*, mtClass> *super_stack) { + ResourceMark rm; + + // print indentation with proper indicators of superclass. + StackIterator<KlassInfoEntry*, mtClass> iter(*super_stack); + while (!iter.is_empty()) { + KlassInfoEntry* super_cie = iter.next(); + st->print("|"); + if (iter.is_empty()) { + st->print("--"); + } else { + st->print(" "); + } + } + + // print the class name + st->print("%s\n", cie->name()); + } + void KlassInfoHisto::print_class_stats(outputStream* st, bool csv_format, const char *columns) { ResourceMark rm; KlassSizeStats sz, sz_sum; int i;
*** 318,365 **** for(i=0; i < elements()->length(); i++) { elements()->at(i)->set_index(i+1); } for (int pass=1; pass<=2; pass++) { if (pass == 2) { print_title(st, csv_format, selected, width_table, name_table); } for(i=0; i < elements()->length(); i++) { KlassInfoEntry* e = (KlassInfoEntry*)elements()->at(i); const Klass* k = e->klass(); memset(&sz, 0, sizeof(sz)); sz._inst_count = e->count(); sz._inst_bytes = HeapWordSize * e->words(); k->collect_statistics(&sz); sz._total_bytes = sz._ro_bytes + sz._rw_bytes; if (pass == 1) { for (int c=0; c<KlassSizeStats::_num_columns; c++) { colsum_table[c] += col_table[c]; } } else { ! int super_index = -1; if (k->oop_is_instance()) { Klass* super = ((InstanceKlass*)k)->java_super(); if (super) { KlassInfoEntry* super_e = _cit->lookup(super); if (super_e) { ! super_index = super_e->index(); } } } if (csv_format) { ! st->print("%d,%d", e->index(), super_index); for (int c=0; c<KlassSizeStats::_num_columns; c++) { if (selected[c]) {st->print("," JULONG_FORMAT, col_table[c]);} } st->print(",%s",e->name()); } else { ! st->print("%5d %5d", e->index(), super_index); for (int c=0; c<KlassSizeStats::_num_columns; c++) { if (selected[c]) {print_julong(st, width_table[c], col_table[c]);} } st->print(" %s", e->name()); } --- 431,482 ---- for(i=0; i < elements()->length(); i++) { elements()->at(i)->set_index(i+1); } + // First iteration is for accumulating stats totals in colsum_table[]. + // Second iteration is for printing stats for each class. for (int pass=1; pass<=2; pass++) { if (pass == 2) { print_title(st, csv_format, selected, width_table, name_table); } for(i=0; i < elements()->length(); i++) { KlassInfoEntry* e = (KlassInfoEntry*)elements()->at(i); const Klass* k = e->klass(); + // Get the stats for this class memset(&sz, 0, sizeof(sz)); sz._inst_count = e->count(); sz._inst_bytes = HeapWordSize * e->words(); k->collect_statistics(&sz); sz._total_bytes = sz._ro_bytes + sz._rw_bytes; if (pass == 1) { + // Add the stats for this class to the overall totals for (int c=0; c<KlassSizeStats::_num_columns; c++) { colsum_table[c] += col_table[c]; } } else { ! // Print the stats for this class. if (k->oop_is_instance()) { Klass* super = ((InstanceKlass*)k)->java_super(); if (super) { KlassInfoEntry* super_e = _cit->lookup(super); if (super_e) { ! e->set_super_index(super_e->index()); } } } if (csv_format) { ! st->print("%d,%d", e->index(), e->super_index()); for (int c=0; c<KlassSizeStats::_num_columns; c++) { if (selected[c]) {st->print("," JULONG_FORMAT, col_table[c]);} } st->print(",%s",e->name()); } else { ! st->print("%5d %5d", e->index(), e->super_index()); for (int c=0; c<KlassSizeStats::_num_columns; c++) { if (selected[c]) {print_julong(st, width_table[c], col_table[c]);} } st->print(" %s", e->name()); }
*** 371,388 **** --- 488,508 ---- st->cr(); } } if (pass == 1) { + // Calculate the minimum width needed for the column by accounting for the + // column header width and the width of the largest value in the column. for (int c=0; c<KlassSizeStats::_num_columns; c++) { width_table[c] = col_width(colsum_table[c], name_table[c]); } } } sz_sum._inst_size = 0; + // Print the column totals. if (csv_format) { st->print(","); for (int c=0; c<KlassSizeStats::_num_columns; c++) { if (selected[c]) {st->print("," JULONG_FORMAT, colsum_table[c]);} }
*** 512,521 **** --- 632,642 ---- return; } KlassInfoTable cit(_print_class_stats); if (!cit.allocation_failed()) { + // populate table with object allocation info 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);