KlassInfoEntry* KlassInfoTable::lookup(Klass* 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; }
void KlassInfoHisto::print_class_stats(outputStream* st, bool csv_format, const char *columns) { ResourceMark rm; KlassSizeStats sz, sz_sum; int i; julong *col_table = (julong*)(&sz); julong *colsum_table = (julong*)(&sz_sum); int width_table[KlassSizeStats::_num_columns]; bool selected[KlassSizeStats::_num_columns]; _selected_columns = columns; memset(&sz_sum, 0, sizeof(sz_sum)); for (int c=0; c<KlassSizeStats::_num_columns; c++) { selected[c] = is_selected(name_table[c]); } 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()); } if (is_selected("ClassLoader")) { ClassLoaderData* loader_data = k->class_loader_data(); st->print(","); loader_data->print_value_on(st); } st->cr(); } } if (pass == 1) { 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; if (csv_format) { st->print(","); for (int c=0; c<KlassSizeStats::_num_columns; c++) { if (selected[c]) {st->print("," JULONG_FORMAT, colsum_table[c]);} } } else { st->print(" "); for (int c=0; c<KlassSizeStats::_num_columns; c++) { if (selected[c]) {print_julong(st, width_table[c], colsum_table[c]);} } st->print(" Total"); if (sz_sum._total_bytes > 0) { st->cr(); st->print(" "); for (int c=0; c<KlassSizeStats::_num_columns; c++) { if (selected[c]) { switch (c) { case KlassSizeStats::_index_inst_size: case KlassSizeStats::_index_inst_count: case KlassSizeStats::_index_method_count: PRAGMA_DIAG_PUSH PRAGMA_FORMAT_NONLITERAL_IGNORED_INTERNAL st->print(str_fmt(width_table[c]), "-"); PRAGMA_DIAG_POP break; default: { double perc = (double)(100) * (double)(colsum_table[c]) / (double)sz_sum._total_bytes; PRAGMA_DIAG_PUSH PRAGMA_FORMAT_NONLITERAL_IGNORED_INTERNAL st->print(perc_fmt(width_table[c]), perc); PRAGMA_DIAG_POP } } } } } }
void KlassInfoHisto::print_class_stats(outputStream* st, bool csv_format, const char *columns) { ResourceMark rm; KlassSizeStats sz, sz_sum; int i; julong *col_table = (julong*)(&sz); julong *colsum_table = (julong*)(&sz_sum); int width_table[KlassSizeStats::_num_columns]; bool selected[KlassSizeStats::_num_columns]; _selected_columns = columns; memset(&sz_sum, 0, sizeof(sz_sum)); for (int c=0; c<KlassSizeStats::_num_columns; c++) { selected[c] = is_selected(name_table[c]); } 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 { int super_index = -1; // Print the stats for this class. if (k->is_instance_klass()) { Klass* super = k->super(); if (super) { KlassInfoEntry* super_e = _cit->lookup(super); if (super_e) { super_index = super_e->index(); } } } if (csv_format) { st->print("%ld,%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("%5ld %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()); } if (is_selected("ClassLoader")) { ClassLoaderData* loader_data = k->class_loader_data(); st->print(","); loader_data->print_value_on(st); } 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]);} } } else { st->print(" "); for (int c=0; c<KlassSizeStats::_num_columns; c++) { if (selected[c]) {print_julong(st, width_table[c], colsum_table[c]);} } st->print(" Total"); if (sz_sum._total_bytes > 0) { st->cr(); st->print(" "); for (int c=0; c<KlassSizeStats::_num_columns; c++) { if (selected[c]) { switch (c) { case KlassSizeStats::_index_inst_size: case KlassSizeStats::_index_inst_count: case KlassSizeStats::_index_method_count: st->print("%*s", width_table[c], "-"); break; default: { double perc = (double)(100) * (double)(colsum_table[c]) / (double)sz_sum._total_bytes; st->print("%*.1f%%", width_table[c]-1, perc); } } } } } } st->cr(); if (!csv_format) { print_title(st, csv_format, selected, width_table, name_table); } }
void KlassHierarchy::print_class_hierarchy(outputStream* st, bool print_interfaces, bool print_subclasses, char* classname) { ResourceMark rm; Stack <KlassInfoEntry*, mtClass> class_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("ERROR: 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); for(int i = 0; i < elements.length(); i++) { KlassInfoEntry* cie = elements.at(i); const InstanceKlass* k = (InstanceKlass*)cie->klass(); Klass* super = ((InstanceKlass*)k)->java_super(); // Set the index for the class. cie->set_index(i + 1); // Add the class to the subclass array of its superclass. if (super != NULL) { KlassInfoEntry* super_cie = cit.lookup(super); assert(super_cie != NULL, "could not lookup superclass"); super_cie->add_subclass(cie); } } // Set the do_print flag for each class that should be printed. for(int i = 0; i < elements.length(); i++) { KlassInfoEntry* cie = elements.at(i); if (classname == NULL) { // We are printing all classes. cie->set_do_print(true); } else { // We are only printing the hierarchy of a specific class. if (strcmp(classname, cie->klass()->external_name()) == 0) { KlassHierarchy::set_do_print_for_class_hierarchy(cie, &cit, print_subclasses); } } } // 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. while (!class_stack.is_empty()) { KlassInfoEntry* curr_cie = class_stack.pop(); if (curr_cie->do_print()) { print_class(st, curr_cie, print_interfaces); 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++) { KlassInfoEntry* cie = curr_cie->subclasses()->at(i); if (cie->do_print()) { class_stack.push(cie); } } } } } st->flush(); }
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; }