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