297 st->print(",ClassLoader"); |
311 st->print(",ClassLoader"); |
298 } |
312 } |
299 st->cr(); |
313 st->cr(); |
300 } |
314 } |
301 |
315 |
|
316 class HierarchyClosure : public KlassInfoClosure { |
|
317 private: |
|
318 GrowableArray<KlassInfoEntry*> *_elements; |
|
319 public: |
|
320 HierarchyClosure(GrowableArray<KlassInfoEntry*> *_elements) : _elements(_elements) {} |
|
321 |
|
322 void do_cinfo(KlassInfoEntry* cie) { |
|
323 // ignore array classes |
|
324 if (cie->klass()->oop_is_instance()) { |
|
325 _elements->append(cie); |
|
326 } |
|
327 } |
|
328 }; |
|
329 |
|
330 void KlassHierarchy::print_class_hierarchy(outputStream* st, bool print_interfaces, |
|
331 bool print_subclasses, char* classname) { |
|
332 ResourceMark rm; |
|
333 Stack <KlassInfoEntry*, mtClass> class_stack; |
|
334 GrowableArray<KlassInfoEntry*> elements; |
|
335 |
|
336 // Add all classes to the KlassInfoTable, which allows for quick lookup. |
|
337 // A KlassInfoEntry will be created for each class. |
|
338 KlassInfoTable cit(true); |
|
339 if (cit.allocation_failed()) { |
|
340 st->print_cr("ERROR: Ran out of C-heap; hierarchy not generated"); |
|
341 return; |
|
342 } |
|
343 |
|
344 // Add all created KlassInfoEntry instances to the elements array for easy |
|
345 // iteration, and to allow each KlassInfoEntry instance to have a unique index. |
|
346 HierarchyClosure hc(&elements); |
|
347 cit.iterate(&hc); |
|
348 |
|
349 for(int i = 0; i < elements.length(); i++) { |
|
350 KlassInfoEntry* cie = elements.at(i); |
|
351 const InstanceKlass* k = (InstanceKlass*)cie->klass(); |
|
352 Klass* super = ((InstanceKlass*)k)->java_super(); |
|
353 |
|
354 // Set the index for the class. |
|
355 cie->set_index(i + 1); |
|
356 |
|
357 // Add the class to the subclass array of its superclass. |
|
358 if (super != NULL) { |
|
359 KlassInfoEntry* super_cie = cit.lookup(super); |
|
360 assert(super_cie != NULL, "could not lookup superclass"); |
|
361 super_cie->add_subclass(cie); |
|
362 } |
|
363 } |
|
364 |
|
365 // Set the do_print flag for each class that should be printed. |
|
366 for(int i = 0; i < elements.length(); i++) { |
|
367 KlassInfoEntry* cie = elements.at(i); |
|
368 if (classname == NULL) { |
|
369 // We are printing all classes. |
|
370 cie->set_do_print(true); |
|
371 } else { |
|
372 // We are only printing the hierarchy of a specific class. |
|
373 if (strcmp(classname, cie->klass()->external_name()) == 0) { |
|
374 KlassHierarchy::set_do_print_for_class_hierarchy(cie, &cit, print_subclasses); |
|
375 } |
|
376 } |
|
377 } |
|
378 |
|
379 // Now we do a depth first traversal of the class hierachry. The class_stack will |
|
380 // maintain the list of classes we still need to process. Start things off |
|
381 // by priming it with java.lang.Object. |
|
382 KlassInfoEntry* jlo_cie = cit.lookup(SystemDictionary::Object_klass()); |
|
383 assert(jlo_cie != NULL, "could not lookup java.lang.Object"); |
|
384 class_stack.push(jlo_cie); |
|
385 |
|
386 // Repeatedly pop the top item off the stack, print its class info, |
|
387 // and push all of its subclasses on to the stack. Do this until there |
|
388 // are no classes left on the stack. |
|
389 while (!class_stack.is_empty()) { |
|
390 KlassInfoEntry* curr_cie = class_stack.pop(); |
|
391 if (curr_cie->do_print()) { |
|
392 print_class(st, curr_cie, print_interfaces); |
|
393 if (curr_cie->subclasses() != NULL) { |
|
394 // Current class has subclasses, so push all of them onto the stack. |
|
395 for (int i = 0; i < curr_cie->subclasses()->length(); i++) { |
|
396 KlassInfoEntry* cie = curr_cie->subclasses()->at(i); |
|
397 if (cie->do_print()) { |
|
398 class_stack.push(cie); |
|
399 } |
|
400 } |
|
401 } |
|
402 } |
|
403 } |
|
404 |
|
405 st->flush(); |
|
406 } |
|
407 |
|
408 // Sets the do_print flag for every superclass and subclass of the specified class. |
|
409 void KlassHierarchy::set_do_print_for_class_hierarchy(KlassInfoEntry* cie, KlassInfoTable* cit, |
|
410 bool print_subclasses) { |
|
411 // Set do_print for all superclasses of this class. |
|
412 Klass* super = ((InstanceKlass*)cie->klass())->java_super(); |
|
413 while (super != NULL) { |
|
414 KlassInfoEntry* super_cie = cit->lookup(super); |
|
415 super_cie->set_do_print(true); |
|
416 super = super->super(); |
|
417 } |
|
418 |
|
419 // Set do_print for this class and all of its subclasses. |
|
420 Stack <KlassInfoEntry*, mtClass> class_stack; |
|
421 class_stack.push(cie); |
|
422 while (!class_stack.is_empty()) { |
|
423 KlassInfoEntry* curr_cie = class_stack.pop(); |
|
424 curr_cie->set_do_print(true); |
|
425 if (print_subclasses && curr_cie->subclasses() != NULL) { |
|
426 // Current class has subclasses, so push all of them onto the stack. |
|
427 for (int i = 0; i < curr_cie->subclasses()->length(); i++) { |
|
428 KlassInfoEntry* cie = curr_cie->subclasses()->at(i); |
|
429 class_stack.push(cie); |
|
430 } |
|
431 } |
|
432 } |
|
433 } |
|
434 |
|
435 static void print_indent(outputStream* st, int indent) { |
|
436 while (indent != 0) { |
|
437 st->print("|"); |
|
438 indent--; |
|
439 if (indent != 0) { |
|
440 st->print(" "); |
|
441 } |
|
442 } |
|
443 } |
|
444 |
|
445 // Print the class name and its unique ClassLoader identifer. |
|
446 static void print_classname(outputStream* st, Klass* klass) { |
|
447 oop loader_oop = klass->class_loader_data()->class_loader(); |
|
448 st->print("%s/", klass->external_name()); |
|
449 if (loader_oop == NULL) { |
|
450 st->print("null"); |
|
451 } else { |
|
452 st->print(INTPTR_FORMAT, klass->class_loader_data()); |
|
453 } |
|
454 } |
|
455 |
|
456 static void print_interface(outputStream* st, Klass* intf_klass, const char* intf_type, int indent) { |
|
457 print_indent(st, indent); |
|
458 st->print(" implements "); |
|
459 print_classname(st, intf_klass); |
|
460 st->print(" (%s intf)\n", intf_type); |
|
461 } |
|
462 |
|
463 void KlassHierarchy::print_class(outputStream* st, KlassInfoEntry* cie, bool print_interfaces) { |
|
464 ResourceMark rm; |
|
465 InstanceKlass* klass = (InstanceKlass*)cie->klass(); |
|
466 int indent = 0; |
|
467 |
|
468 // Print indentation with proper indicators of superclass. |
|
469 Klass* super = klass->super(); |
|
470 while (super != NULL) { |
|
471 super = super->super(); |
|
472 indent++; |
|
473 } |
|
474 print_indent(st, indent); |
|
475 if (indent != 0) st->print("--"); |
|
476 |
|
477 // Print the class name, its unique ClassLoader identifer, and if it is an interface. |
|
478 print_classname(st, klass); |
|
479 if (klass->is_interface()) { |
|
480 st->print(" (intf)"); |
|
481 } |
|
482 st->print("\n"); |
|
483 |
|
484 // Print any interfaces the class has. |
|
485 if (print_interfaces) { |
|
486 Array<Klass*>* local_intfs = klass->local_interfaces(); |
|
487 Array<Klass*>* trans_intfs = klass->transitive_interfaces(); |
|
488 for (int i = 0; i < local_intfs->length(); i++) { |
|
489 print_interface(st, local_intfs->at(i), "declared", indent); |
|
490 } |
|
491 for (int i = 0; i < trans_intfs->length(); i++) { |
|
492 Klass* trans_interface = trans_intfs->at(i); |
|
493 // Only print transitive interfaces if they are not also declared. |
|
494 if (!local_intfs->contains(trans_interface)) { |
|
495 print_interface(st, trans_interface, "inherited", indent); |
|
496 } |
|
497 } |
|
498 } |
|
499 } |
|
500 |
302 void KlassInfoHisto::print_class_stats(outputStream* st, |
501 void KlassInfoHisto::print_class_stats(outputStream* st, |
303 bool csv_format, const char *columns) { |
502 bool csv_format, const char *columns) { |
304 ResourceMark rm; |
503 ResourceMark rm; |
305 KlassSizeStats sz, sz_sum; |
504 KlassSizeStats sz, sz_sum; |
306 int i; |
505 int i; |
318 |
517 |
319 for(i=0; i < elements()->length(); i++) { |
518 for(i=0; i < elements()->length(); i++) { |
320 elements()->at(i)->set_index(i+1); |
519 elements()->at(i)->set_index(i+1); |
321 } |
520 } |
322 |
521 |
|
522 // First iteration is for accumulating stats totals in colsum_table[]. |
|
523 // Second iteration is for printing stats for each class. |
323 for (int pass=1; pass<=2; pass++) { |
524 for (int pass=1; pass<=2; pass++) { |
324 if (pass == 2) { |
525 if (pass == 2) { |
325 print_title(st, csv_format, selected, width_table, name_table); |
526 print_title(st, csv_format, selected, width_table, name_table); |
326 } |
527 } |
327 for(i=0; i < elements()->length(); i++) { |
528 for(i=0; i < elements()->length(); i++) { |
328 KlassInfoEntry* e = (KlassInfoEntry*)elements()->at(i); |
529 KlassInfoEntry* e = (KlassInfoEntry*)elements()->at(i); |
329 const Klass* k = e->klass(); |
530 const Klass* k = e->klass(); |
330 |
531 |
|
532 // Get the stats for this class. |
331 memset(&sz, 0, sizeof(sz)); |
533 memset(&sz, 0, sizeof(sz)); |
332 sz._inst_count = e->count(); |
534 sz._inst_count = e->count(); |
333 sz._inst_bytes = HeapWordSize * e->words(); |
535 sz._inst_bytes = HeapWordSize * e->words(); |
334 k->collect_statistics(&sz); |
536 k->collect_statistics(&sz); |
335 sz._total_bytes = sz._ro_bytes + sz._rw_bytes; |
537 sz._total_bytes = sz._ro_bytes + sz._rw_bytes; |
336 |
538 |
337 if (pass == 1) { |
539 if (pass == 1) { |
|
540 // Add the stats for this class to the overall totals. |
338 for (int c=0; c<KlassSizeStats::_num_columns; c++) { |
541 for (int c=0; c<KlassSizeStats::_num_columns; c++) { |
339 colsum_table[c] += col_table[c]; |
542 colsum_table[c] += col_table[c]; |
340 } |
543 } |
341 } else { |
544 } else { |
342 int super_index = -1; |
545 int super_index = -1; |
|
546 // Print the stats for this class. |
343 if (k->oop_is_instance()) { |
547 if (k->oop_is_instance()) { |
344 Klass* super = ((InstanceKlass*)k)->java_super(); |
548 Klass* super = ((InstanceKlass*)k)->java_super(); |
345 if (super) { |
549 if (super) { |
346 KlassInfoEntry* super_e = _cit->lookup(super); |
550 KlassInfoEntry* super_e = _cit->lookup(super); |
347 if (super_e) { |
551 if (super_e) { |