17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 #include "precompiled.hpp"
26 #include "classfile/classLoaderData.inline.hpp"
27 #include "classfile/classLoaderDataGraph.hpp"
28 #include "classfile/moduleEntry.hpp"
29 #include "classfile/vmClasses.hpp"
30 #include "gc/shared/collectedHeap.hpp"
31 #include "logging/log.hpp"
32 #include "logging/logTag.hpp"
33 #include "memory/heapInspection.hpp"
34 #include "memory/resourceArea.hpp"
35 #include "memory/universe.hpp"
36 #include "oops/oop.inline.hpp"
37 #include "runtime/atomic.hpp"
38 #include "runtime/os.hpp"
39 #include "services/memTracker.hpp"
40 #include "utilities/globalDefinitions.hpp"
41 #include "utilities/macros.hpp"
42 #include "utilities/stack.inline.hpp"
43
44 // HeapInspection
45
46 inline KlassInfoEntry::~KlassInfoEntry() {
47 if (_subclasses != NULL) {
48 delete _subclasses;
49 }
50 }
51
52 inline void KlassInfoEntry::add_subclass(KlassInfoEntry* cie) {
53 if (_subclasses == NULL) {
54 _subclasses = new (mtServiceability) GrowableArray<KlassInfoEntry*>(4, mtServiceability);
55 }
56 _subclasses->append(cie);
57 }
58
492 }
493 }
494
495 void KlassInfoHisto::print_histo_on(outputStream* st) {
496 st->print_cr(" num #instances #bytes class name (module)");
497 st->print_cr("-------------------------------------------------------");
498 print_elements(st);
499 }
500
501 class HistoClosure : public KlassInfoClosure {
502 private:
503 KlassInfoHisto* _cih;
504 public:
505 HistoClosure(KlassInfoHisto* cih) : _cih(cih) {}
506
507 void do_cinfo(KlassInfoEntry* cie) {
508 _cih->add(cie);
509 }
510 };
511
512 class RecordInstanceClosure : public ObjectClosure {
513 private:
514 KlassInfoTable* _cit;
515 uintx _missed_count;
516 BoolObjectClosure* _filter;
517 public:
518 RecordInstanceClosure(KlassInfoTable* cit, BoolObjectClosure* filter) :
519 _cit(cit), _missed_count(0), _filter(filter) {}
520
521 void do_object(oop obj) {
522 if (should_visit(obj)) {
523 if (!_cit->record_instance(obj)) {
524 _missed_count++;
525 }
526 }
527 }
528
529 uintx missed_count() { return _missed_count; }
530
531 private:
|
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 #include "precompiled.hpp"
26 #include "classfile/classLoaderData.inline.hpp"
27 #include "classfile/classLoaderDataGraph.hpp"
28 #include "classfile/moduleEntry.hpp"
29 #include "classfile/vmClasses.hpp"
30 #include "gc/shared/collectedHeap.hpp"
31 #include "logging/log.hpp"
32 #include "logging/logTag.hpp"
33 #include "memory/heapInspection.hpp"
34 #include "memory/resourceArea.hpp"
35 #include "memory/universe.hpp"
36 #include "oops/oop.inline.hpp"
37 #include "oops/inlineKlass.inline.hpp"
38 #include "runtime/reflectionUtils.hpp"
39 #include "runtime/atomic.hpp"
40 #include "runtime/os.hpp"
41 #include "runtime/fieldDescriptor.inline.hpp"
42 #include "services/memTracker.hpp"
43 #include "utilities/globalDefinitions.hpp"
44 #include "utilities/macros.hpp"
45 #include "utilities/stack.inline.hpp"
46
47 // HeapInspection
48
49 inline KlassInfoEntry::~KlassInfoEntry() {
50 if (_subclasses != NULL) {
51 delete _subclasses;
52 }
53 }
54
55 inline void KlassInfoEntry::add_subclass(KlassInfoEntry* cie) {
56 if (_subclasses == NULL) {
57 _subclasses = new (mtServiceability) GrowableArray<KlassInfoEntry*>(4, mtServiceability);
58 }
59 _subclasses->append(cie);
60 }
61
495 }
496 }
497
498 void KlassInfoHisto::print_histo_on(outputStream* st) {
499 st->print_cr(" num #instances #bytes class name (module)");
500 st->print_cr("-------------------------------------------------------");
501 print_elements(st);
502 }
503
504 class HistoClosure : public KlassInfoClosure {
505 private:
506 KlassInfoHisto* _cih;
507 public:
508 HistoClosure(KlassInfoHisto* cih) : _cih(cih) {}
509
510 void do_cinfo(KlassInfoEntry* cie) {
511 _cih->add(cie);
512 }
513 };
514
515
516 class FindClassByNameClosure : public KlassInfoClosure {
517 private:
518 GrowableArray<Klass*>* _klasses;
519 Symbol* _classname;
520 public:
521 FindClassByNameClosure(GrowableArray<Klass*>* klasses, Symbol* classname) :
522 _klasses(klasses), _classname(classname) { }
523
524 void do_cinfo(KlassInfoEntry* cie) {
525 if (cie->klass()->name() == _classname) {
526 _klasses->append(cie->klass());
527 }
528 }
529 };
530
531 class FieldDesc {
532 private:
533 Symbol* _name;
534 Symbol* _signature;
535 int _offset;
536 int _index;
537 InstanceKlass* _holder;
538 AccessFlags _access_flags;
539 public:
540 FieldDesc() {
541 _name = NULL;
542 _signature = NULL;
543 _offset = -1;
544 _index = -1;
545 _holder = NULL;
546 _access_flags = AccessFlags();
547 }
548 FieldDesc(fieldDescriptor& fd) {
549 _name = fd.name();
550 _signature = fd.signature();
551 _offset = fd.offset();
552 _index = fd.index();
553 _holder = fd.field_holder();
554 _access_flags = fd.access_flags();
555 }
556 const Symbol* name() { return _name;}
557 const Symbol* signature() { return _signature; }
558 const int offset() { return _offset; }
559 const int index() { return _index; }
560 const InstanceKlass* holder() { return _holder; }
561 const AccessFlags& access_flags() { return _access_flags; }
562 const bool is_inline_type() { return Signature::basic_type(_signature) == T_PRIMITIVE_OBJECT; }
563 };
564
565 static int compare_offset(FieldDesc* f1, FieldDesc* f2) {
566 return f1->offset() > f2->offset() ? 1 : -1;
567 }
568
569 static void print_field(outputStream* st, int level, int offset, FieldDesc& fd, bool is_inline_type, bool is_inlined ) {
570 const char* inlined_msg = "";
571 if (is_inline_type) {
572 inlined_msg = is_inlined ? "inlined" : "not inlined";
573 }
574 st->print_cr(" @ %d %*s \"%s\" %s %s %s",
575 offset, level * 3, "",
576 fd.name()->as_C_string(),
577 fd.signature()->as_C_string(),
578 is_inline_type ? " // inline type " : "",
579 inlined_msg);
580 }
581
582 static void print_inlined_field(outputStream* st, int level, int offset, InstanceKlass* klass) {
583 assert(klass->is_inline_klass(), "Only inline types can be inlined");
584 InlineKlass* vklass = InlineKlass::cast(klass);
585 GrowableArray<FieldDesc>* fields = new (mtServiceability) GrowableArray<FieldDesc>(100, mtServiceability);
586 for (FieldStream fd(klass, false, false); !fd.eos(); fd.next()) {
587 if (!fd.access_flags().is_static()) {
588 fields->append(FieldDesc(fd.field_descriptor()));
589 }
590 }
591 fields->sort(compare_offset);
592 for(int i = 0; i < fields->length(); i++) {
593 FieldDesc fd = fields->at(i);
594 int offset2 = offset + fd.offset() - vklass->first_field_offset();
595 print_field(st, level, offset2, fd,
596 fd.is_inline_type(), fd.holder()->field_is_inlined(fd.index()));
597 if (fd.holder()->field_is_inlined(fd.index())) {
598 print_inlined_field(st, level + 1, offset2 ,
599 InstanceKlass::cast(fd.holder()->get_inline_type_field_klass(fd.index())));
600 }
601 }
602 }
603
604 void PrintClassLayout::print_class_layout(outputStream* st, char* class_name) {
605 KlassInfoTable cit(true);
606 if (cit.allocation_failed()) {
607 st->print_cr("ERROR: Ran out of C-heap; hierarchy not generated");
608 return;
609 }
610
611 Thread* THREAD = Thread::current();
612
613 Symbol* classname = SymbolTable::probe(class_name, (int)strlen(class_name));
614
615 GrowableArray<Klass*>* klasses = new (mtServiceability) GrowableArray<Klass*>(100, mtServiceability);
616
617 FindClassByNameClosure fbnc(klasses, classname);
618 cit.iterate(&fbnc);
619
620 for(int i = 0; i < klasses->length(); i++) {
621 Klass* klass = klasses->at(i);
622 if (!klass->is_instance_klass()) continue; // Skip
623 InstanceKlass* ik = InstanceKlass::cast(klass);
624 int tab = 1;
625 st->print_cr("Class %s [@%s]:", klass->name()->as_C_string(),
626 klass->class_loader_data()->loader_name());
627 ResourceMark rm;
628 GrowableArray<FieldDesc>* fields = new (mtServiceability) GrowableArray<FieldDesc>(100, mtServiceability);
629 for (FieldStream fd(ik, false, false); !fd.eos(); fd.next()) {
630 if (!fd.access_flags().is_static()) {
631 fields->append(FieldDesc(fd.field_descriptor()));
632 }
633 }
634 fields->sort(compare_offset);
635 for(int i = 0; i < fields->length(); i++) {
636 FieldDesc fd = fields->at(i);
637 print_field(st, 0, fd.offset(), fd, fd.is_inline_type(), fd.holder()->field_is_inlined(fd.index()));
638 if (fd.holder()->field_is_inlined(fd.index())) {
639 print_inlined_field(st, 1, fd.offset(),
640 InstanceKlass::cast(fd.holder()->get_inline_type_field_klass(fd.index())));
641 }
642 }
643 }
644 st->cr();
645 }
646
647 class RecordInstanceClosure : public ObjectClosure {
648 private:
649 KlassInfoTable* _cit;
650 uintx _missed_count;
651 BoolObjectClosure* _filter;
652 public:
653 RecordInstanceClosure(KlassInfoTable* cit, BoolObjectClosure* filter) :
654 _cit(cit), _missed_count(0), _filter(filter) {}
655
656 void do_object(oop obj) {
657 if (should_visit(obj)) {
658 if (!_cit->record_instance(obj)) {
659 _missed_count++;
660 }
661 }
662 }
663
664 uintx missed_count() { return _missed_count; }
665
666 private:
|