< prev index next >

src/hotspot/share/memory/heapInspection.cpp

Print this page

 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/reflectionAccessorImplKlassHelper.hpp"


 38 #include "runtime/atomic.hpp"
 39 #include "runtime/os.hpp"

 40 #include "services/memTracker.hpp"
 41 #include "utilities/globalDefinitions.hpp"
 42 #include "utilities/macros.hpp"
 43 #include "utilities/stack.inline.hpp"
 44 
 45 // HeapInspection
 46 
 47 inline KlassInfoEntry::~KlassInfoEntry() {
 48   if (_subclasses != NULL) {
 49     delete _subclasses;
 50   }
 51 }
 52 
 53 inline void KlassInfoEntry::add_subclass(KlassInfoEntry* cie) {
 54   if (_subclasses == NULL) {
 55     _subclasses = new  (ResourceObj::C_HEAP, mtServiceability) GrowableArray<KlassInfoEntry*>(4, mtServiceability);
 56   }
 57   _subclasses->append(cie);
 58 }
 59 

499   }
500 }
501 
502 void KlassInfoHisto::print_histo_on(outputStream* st) {
503   st->print_cr(" num     #instances         #bytes  class name (module)");
504   st->print_cr("-------------------------------------------------------");
505   print_elements(st);
506 }
507 
508 class HistoClosure : public KlassInfoClosure {
509  private:
510   KlassInfoHisto* _cih;
511  public:
512   HistoClosure(KlassInfoHisto* cih) : _cih(cih) {}
513 
514   void do_cinfo(KlassInfoEntry* cie) {
515     _cih->add(cie);
516   }
517 };
518 




































































































































519 class RecordInstanceClosure : public ObjectClosure {
520  private:
521   KlassInfoTable* _cit;
522   uintx _missed_count;
523   BoolObjectClosure* _filter;
524  public:
525   RecordInstanceClosure(KlassInfoTable* cit, BoolObjectClosure* filter) :
526     _cit(cit), _missed_count(0), _filter(filter) {}
527 
528   void do_object(oop obj) {
529     if (should_visit(obj)) {
530       if (!_cit->record_instance(obj)) {
531         _missed_count++;
532       }
533     }
534   }
535 
536   uintx missed_count() { return _missed_count; }
537 
538  private:

 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/reflectionAccessorImplKlassHelper.hpp"
 38 #include "oops/inlineKlass.inline.hpp"
 39 #include "runtime/reflectionUtils.hpp"
 40 #include "runtime/atomic.hpp"
 41 #include "runtime/os.hpp"
 42 #include "runtime/fieldDescriptor.inline.hpp"
 43 #include "services/memTracker.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 != NULL) {
 52     delete _subclasses;
 53   }
 54 }
 55 
 56 inline void KlassInfoEntry::add_subclass(KlassInfoEntry* cie) {
 57   if (_subclasses == NULL) {
 58     _subclasses = new  (ResourceObj::C_HEAP, mtServiceability) GrowableArray<KlassInfoEntry*>(4, mtServiceability);
 59   }
 60   _subclasses->append(cie);
 61 }
 62 

502   }
503 }
504 
505 void KlassInfoHisto::print_histo_on(outputStream* st) {
506   st->print_cr(" num     #instances         #bytes  class name (module)");
507   st->print_cr("-------------------------------------------------------");
508   print_elements(st);
509 }
510 
511 class HistoClosure : public KlassInfoClosure {
512  private:
513   KlassInfoHisto* _cih;
514  public:
515   HistoClosure(KlassInfoHisto* cih) : _cih(cih) {}
516 
517   void do_cinfo(KlassInfoEntry* cie) {
518     _cih->add(cie);
519   }
520 };
521 
522 
523 class FindClassByNameClosure : public KlassInfoClosure {
524  private:
525   GrowableArray<Klass*>* _klasses;
526   Symbol* _classname;
527  public:
528   FindClassByNameClosure(GrowableArray<Klass*>* klasses, Symbol* classname) :
529     _klasses(klasses), _classname(classname) { }
530 
531   void do_cinfo(KlassInfoEntry* cie) {
532     if (cie->klass()->name() == _classname) {
533       _klasses->append(cie->klass());
534     }
535   }
536 };
537 
538 class FieldDesc {
539 private:
540   Symbol* _name;
541   Symbol* _signature;
542   int _offset;
543   int _index;
544   InstanceKlass* _holder;
545   AccessFlags _access_flags;
546  public:
547   FieldDesc() {
548     _name = NULL;
549     _signature = NULL;
550     _offset = -1;
551     _index = -1;
552     _holder = NULL;
553     _access_flags = AccessFlags();
554   }
555   FieldDesc(fieldDescriptor& fd) {
556     _name = fd.name();
557     _signature = fd.signature();
558     _offset = fd.offset();
559     _index = fd.index();
560     _holder = fd.field_holder();
561     _access_flags = fd.access_flags();
562   }
563   const Symbol* name() { return _name;}
564   const Symbol* signature() { return _signature; }
565   const int offset() { return _offset; }
566   const int index() { return _index; }
567   const InstanceKlass* holder() { return _holder; }
568   const AccessFlags& access_flags() { return _access_flags; }
569   const bool is_inline_type() { return Signature::basic_type(_signature) == T_INLINE_TYPE; }
570 };
571 
572 static int compare_offset(FieldDesc* f1, FieldDesc* f2) {
573    return f1->offset() > f2->offset() ? 1 : -1;
574 }
575 
576 static void print_field(outputStream* st, int level, int offset, FieldDesc& fd, bool is_inline_type, bool is_inlined ) {
577   const char* inlined_msg = "";
578   if (is_inline_type) {
579     inlined_msg = is_inlined ? "inlined" : "not inlined";
580   }
581   st->print_cr("  @ %d %*s \"%s\" %s %s %s",
582       offset, level * 3, "",
583       fd.name()->as_C_string(),
584       fd.signature()->as_C_string(),
585       is_inline_type ? " // inline type " : "",
586       inlined_msg);
587 }
588 
589 static void print_inlined_field(outputStream* st, int level, int offset, InstanceKlass* klass) {
590   assert(klass->is_inline_klass(), "Only inline types can be inlined");
591   InlineKlass* vklass = InlineKlass::cast(klass);
592   GrowableArray<FieldDesc>* fields = new (ResourceObj::C_HEAP, mtServiceability) GrowableArray<FieldDesc>(100, mtServiceability);
593   for (FieldStream fd(klass, false, false); !fd.eos(); fd.next()) {
594     if (!fd.access_flags().is_static()) {
595       fields->append(FieldDesc(fd.field_descriptor()));
596     }
597   }
598   fields->sort(compare_offset);
599   for(int i = 0; i < fields->length(); i++) {
600     FieldDesc fd = fields->at(i);
601     int offset2 = offset + fd.offset() - vklass->first_field_offset();
602     print_field(st, level, offset2, fd,
603         fd.is_inline_type(), fd.holder()->field_is_inlined(fd.index()));
604     if (fd.holder()->field_is_inlined(fd.index())) {
605       print_inlined_field(st, level + 1, offset2 ,
606           InstanceKlass::cast(fd.holder()->get_inline_type_field_klass(fd.index())));
607     }
608   }
609 }
610 
611 void PrintClassLayout::print_class_layout(outputStream* st, char* class_name) {
612   KlassInfoTable cit(true);
613   if (cit.allocation_failed()) {
614     st->print_cr("ERROR: Ran out of C-heap; hierarchy not generated");
615     return;
616   }
617 
618   Thread* THREAD = Thread::current();
619 
620   Symbol* classname = SymbolTable::probe(class_name, (int)strlen(class_name));
621 
622   GrowableArray<Klass*>* klasses = new (ResourceObj::C_HEAP, mtServiceability) GrowableArray<Klass*>(100, mtServiceability);
623 
624   FindClassByNameClosure fbnc(klasses, classname);
625   cit.iterate(&fbnc);
626 
627   for(int i = 0; i < klasses->length(); i++) {
628     Klass* klass = klasses->at(i);
629     if (!klass->is_instance_klass()) continue;  // Skip
630     InstanceKlass* ik = InstanceKlass::cast(klass);
631     int tab = 1;
632     st->print_cr("Class %s [@%s]:", klass->name()->as_C_string(),
633         klass->class_loader_data()->loader_name());
634     ResourceMark rm;
635     GrowableArray<FieldDesc>* fields = new (ResourceObj::C_HEAP, mtServiceability) GrowableArray<FieldDesc>(100, mtServiceability);
636     for (FieldStream fd(ik, false, false); !fd.eos(); fd.next()) {
637       if (!fd.access_flags().is_static()) {
638         fields->append(FieldDesc(fd.field_descriptor()));
639       }
640     }
641     fields->sort(compare_offset);
642     for(int i = 0; i < fields->length(); i++) {
643       FieldDesc fd = fields->at(i);
644       print_field(st, 0, fd.offset(), fd, fd.is_inline_type(), fd.holder()->field_is_inlined(fd.index()));
645       if (fd.holder()->field_is_inlined(fd.index())) {
646         print_inlined_field(st, 1, fd.offset(),
647             InstanceKlass::cast(fd.holder()->get_inline_type_field_klass(fd.index())));
648       }
649     }
650   }
651   st->cr();
652 }
653 
654 class RecordInstanceClosure : public ObjectClosure {
655  private:
656   KlassInfoTable* _cit;
657   uintx _missed_count;
658   BoolObjectClosure* _filter;
659  public:
660   RecordInstanceClosure(KlassInfoTable* cit, BoolObjectClosure* filter) :
661     _cit(cit), _missed_count(0), _filter(filter) {}
662 
663   void do_object(oop obj) {
664     if (should_visit(obj)) {
665       if (!_cit->record_instance(obj)) {
666         _missed_count++;
667       }
668     }
669   }
670 
671   uintx missed_count() { return _missed_count; }
672 
673  private:
< prev index next >