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 "nmt/memTracker.hpp"
37 #include "oops/oop.inline.hpp"
38 #include "runtime/atomic.hpp"
39 #include "runtime/os.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 != nullptr) {
48 delete _subclasses;
49 }
50 }
51
52 inline void KlassInfoEntry::add_subclass(KlassInfoEntry* cie) {
53 if (_subclasses == nullptr) {
54 _subclasses = new (mtServiceability) GrowableArray<KlassInfoEntry*>(4, mtServiceability);
55 }
56 _subclasses->append(cie);
57 }
58
59 int KlassInfoEntry::compare(KlassInfoEntry* e1, KlassInfoEntry* e2) {
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 "nmt/memTracker.hpp"
37 #include "oops/fieldInfo.hpp"
38 #include "oops/fieldStreams.inline.hpp"
39 #include "oops/oop.inline.hpp"
40 #include "oops/inlineKlass.inline.hpp"
41 #include "runtime/atomic.hpp"
42 #include "runtime/os.hpp"
43 #include "runtime/fieldDescriptor.inline.hpp"
44 #include "utilities/globalDefinitions.hpp"
45 #include "utilities/macros.hpp"
46 #include "utilities/stack.inline.hpp"
47
48 // HeapInspection
49
50 inline KlassInfoEntry::~KlassInfoEntry() {
51 if (_subclasses != nullptr) {
52 delete _subclasses;
53 }
54 }
55
56 inline void KlassInfoEntry::add_subclass(KlassInfoEntry* cie) {
57 if (_subclasses == nullptr) {
58 _subclasses = new (mtServiceability) GrowableArray<KlassInfoEntry*>(4, mtServiceability);
59 }
60 _subclasses->append(cie);
61 }
62
63 int KlassInfoEntry::compare(KlassInfoEntry* e1, KlassInfoEntry* e2) {
496 }
497 }
498
499 void KlassInfoHisto::print_histo_on(outputStream* st) {
500 st->print_cr(" num #instances #bytes class name (module)");
501 st->print_cr("-------------------------------------------------------");
502 print_elements(st);
503 }
504
505 class HistoClosure : public KlassInfoClosure {
506 private:
507 KlassInfoHisto* _cih;
508 public:
509 HistoClosure(KlassInfoHisto* cih) : _cih(cih) {}
510
511 void do_cinfo(KlassInfoEntry* cie) {
512 _cih->add(cie);
513 }
514 };
515
516
517 class FindClassByNameClosure : public KlassInfoClosure {
518 private:
519 GrowableArray<Klass*>* _klasses;
520 Symbol* _classname;
521 public:
522 FindClassByNameClosure(GrowableArray<Klass*>* klasses, Symbol* classname) :
523 _klasses(klasses), _classname(classname) { }
524
525 void do_cinfo(KlassInfoEntry* cie) {
526 if (cie->klass()->name() == _classname) {
527 _klasses->append(cie->klass());
528 }
529 }
530 };
531
532 class FieldDesc {
533 private:
534 Symbol* _name;
535 Symbol* _signature;
536 int _offset;
537 int _index;
538 InstanceKlass* _holder;
539 AccessFlags _access_flags;
540 FieldInfo::FieldFlags _field_flags;
541 public:
542 FieldDesc() : _name(nullptr), _signature(nullptr), _offset(-1), _index(-1), _holder(nullptr),
543 _access_flags(AccessFlags()), _field_flags(FieldInfo::FieldFlags((u4)0)) { }
544
545 FieldDesc(fieldDescriptor& fd) : _name(fd.name()), _signature(fd.signature()), _offset(fd.offset()),
546 _index(fd.index()), _holder(fd.field_holder()),
547 _access_flags(fd.access_flags()), _field_flags(fd.field_flags()) { }
548
549 const Symbol* name() { return _name;}
550 const Symbol* signature() { return _signature; }
551 int offset() const { return _offset; }
552 int index() const { return _index; }
553 const InstanceKlass* holder() { return _holder; }
554 const AccessFlags& access_flags() { return _access_flags; }
555 bool is_null_free_inline_type() const { return _field_flags.is_null_free_inline_type(); }
556 };
557
558 static int compare_offset(FieldDesc* f1, FieldDesc* f2) {
559 return f1->offset() > f2->offset() ? 1 : -1;
560 }
561
562 static void print_field(outputStream* st, int level, int offset, FieldDesc& fd, bool is_inline_type, bool is_flat ) {
563 const char* flat_field_msg = "";
564 if (is_flat) {
565 flat_field_msg = is_flat ? "flat" : "not flat";
566 }
567 st->print_cr(" @ %d %*s \"%s\" %s %s %s",
568 offset, level * 3, "",
569 fd.name()->as_C_string(),
570 fd.signature()->as_C_string(),
571 is_inline_type ? " // inline type " : "",
572 flat_field_msg);
573 }
574
575 static void print_flat_field(outputStream* st, int level, int offset, InstanceKlass* klass) {
576 assert(klass->is_inline_klass(), "Only inline types can be flat");
577 InlineKlass* vklass = InlineKlass::cast(klass);
578 GrowableArray<FieldDesc>* fields = new (mtServiceability) GrowableArray<FieldDesc>(100, mtServiceability);
579 for (AllFieldStream fd(klass); !fd.done(); fd.next()) {
580 if (!fd.access_flags().is_static()) {
581 fields->append(FieldDesc(fd.field_descriptor()));
582 }
583 }
584 fields->sort(compare_offset);
585 for(int i = 0; i < fields->length(); i++) {
586 FieldDesc fd = fields->at(i);
587 int offset2 = offset + fd.offset() - vklass->first_field_offset();
588 print_field(st, level, offset2, fd,
589 fd.is_null_free_inline_type(), fd.holder()->field_is_flat(fd.index()));
590 if (fd.holder()->field_is_flat(fd.index())) {
591 print_flat_field(st, level + 1, offset2 ,
592 InstanceKlass::cast(fd.holder()->get_inline_type_field_klass(fd.index())));
593 }
594 }
595 }
596
597 void PrintClassLayout::print_class_layout(outputStream* st, char* class_name) {
598 KlassInfoTable cit(true);
599 if (cit.allocation_failed()) {
600 st->print_cr("ERROR: Ran out of C-heap; hierarchy not generated");
601 return;
602 }
603
604 Thread* THREAD = Thread::current();
605
606 Symbol* classname = SymbolTable::probe(class_name, (int)strlen(class_name));
607
608 GrowableArray<Klass*>* klasses = new (mtServiceability) GrowableArray<Klass*>(100, mtServiceability);
609
610 FindClassByNameClosure fbnc(klasses, classname);
611 cit.iterate(&fbnc);
612
613 for(int i = 0; i < klasses->length(); i++) {
614 Klass* klass = klasses->at(i);
615 if (!klass->is_instance_klass()) continue; // Skip
616 InstanceKlass* ik = InstanceKlass::cast(klass);
617 int tab = 1;
618 st->print_cr("Class %s [@%s]:", klass->name()->as_C_string(),
619 klass->class_loader_data()->loader_name());
620 ResourceMark rm;
621 GrowableArray<FieldDesc>* fields = new (mtServiceability) GrowableArray<FieldDesc>(100, mtServiceability);
622 for (AllFieldStream fd(ik); !fd.done(); fd.next()) {
623 if (!fd.access_flags().is_static()) {
624 fields->append(FieldDesc(fd.field_descriptor()));
625 }
626 }
627 fields->sort(compare_offset);
628 for(int i = 0; i < fields->length(); i++) {
629 FieldDesc fd = fields->at(i);
630 print_field(st, 0, fd.offset(), fd, fd.is_null_free_inline_type(), fd.holder()->field_is_flat(fd.index()));
631 if (fd.holder()->field_is_flat(fd.index())) {
632 print_flat_field(st, 1, fd.offset(),
633 InstanceKlass::cast(fd.holder()->get_inline_type_field_klass(fd.index())));
634 }
635 }
636 }
637 st->cr();
638 }
639
640 class RecordInstanceClosure : public ObjectClosure {
641 private:
642 KlassInfoTable* _cit;
643 uintx _missed_count;
644 BoolObjectClosure* _filter;
645 public:
646 RecordInstanceClosure(KlassInfoTable* cit, BoolObjectClosure* filter) :
647 _cit(cit), _missed_count(0), _filter(filter) {}
648
649 void do_object(oop obj) {
650 if (should_visit(obj)) {
651 if (!_cit->record_instance(obj)) {
652 _missed_count++;
653 }
654 }
655 }
656
657 uintx missed_count() { return _missed_count; }
658
659 private:
|