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 "precompiled.hpp" 26 #include "classfile/classLoaderData.inline.hpp" 27 #include "classfile/classLoaderDataGraph.hpp" 28 #include "classfile/moduleEntry.hpp" 29 #include "classfile/systemDictionary.hpp" 30 #include "gc/shared/collectedHeap.hpp" 31 #include "memory/heapInspection.hpp" 32 #include "memory/resourceArea.hpp" 33 #include "memory/universe.hpp" 34 #include "oops/oop.inline.hpp" 35 #include "oops/reflectionAccessorImplKlassHelper.hpp" 36 #include "runtime/os.hpp" 37 #include "utilities/globalDefinitions.hpp" 38 #include "utilities/macros.hpp" 39 #include "utilities/stack.inline.hpp" 40 41 // HeapInspection 42 43 int KlassSizeStats::count(oop x) { 44 return (HeapWordSize * (((x) != NULL) ? (x)->size() : 0)); 45 } 46 47 int KlassSizeStats::count_array(objArrayOop x) { 48 return (HeapWordSize * (((x) != NULL) ? (x)->size() : 0)); 49 } 50 51 inline KlassInfoEntry::~KlassInfoEntry() { 52 if (_subclasses != NULL) { 53 delete _subclasses; 54 } 55 } 56 673 if (print_stats) { 674 print_class_stats(st, csv_format, columns); 675 } else { 676 st->print_cr(" num #instances #bytes class name (module)"); 677 st->print_cr("-------------------------------------------------------"); 678 print_elements(st); 679 } 680 } 681 682 class HistoClosure : public KlassInfoClosure { 683 private: 684 KlassInfoHisto* _cih; 685 public: 686 HistoClosure(KlassInfoHisto* cih) : _cih(cih) {} 687 688 void do_cinfo(KlassInfoEntry* cie) { 689 _cih->add(cie); 690 } 691 }; 692 693 class RecordInstanceClosure : public ObjectClosure { 694 private: 695 KlassInfoTable* _cit; 696 size_t _missed_count; 697 BoolObjectClosure* _filter; 698 public: 699 RecordInstanceClosure(KlassInfoTable* cit, BoolObjectClosure* filter) : 700 _cit(cit), _missed_count(0), _filter(filter) {} 701 702 void do_object(oop obj) { 703 if (should_visit(obj)) { 704 if (!_cit->record_instance(obj)) { 705 _missed_count++; 706 } 707 } 708 } 709 710 size_t missed_count() { return _missed_count; } 711 712 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 "precompiled.hpp" 26 #include "classfile/classLoaderData.inline.hpp" 27 #include "classfile/classLoaderDataGraph.hpp" 28 #include "classfile/moduleEntry.hpp" 29 #include "classfile/systemDictionary.hpp" 30 #include "gc/shared/collectedHeap.hpp" 31 #include "memory/heapInspection.hpp" 32 #include "memory/resourceArea.hpp" 33 #include "memory/universe.hpp" 34 #include "oops/oop.inline.hpp" 35 #include "oops/reflectionAccessorImplKlassHelper.hpp" 36 #include "oops/valueKlass.hpp" 37 #include "runtime/os.hpp" 38 #include "runtime/fieldDescriptor.inline.hpp" 39 #include "utilities/globalDefinitions.hpp" 40 #include "utilities/macros.hpp" 41 #include "utilities/stack.inline.hpp" 42 43 // HeapInspection 44 45 int KlassSizeStats::count(oop x) { 46 return (HeapWordSize * (((x) != NULL) ? (x)->size() : 0)); 47 } 48 49 int KlassSizeStats::count_array(objArrayOop x) { 50 return (HeapWordSize * (((x) != NULL) ? (x)->size() : 0)); 51 } 52 53 inline KlassInfoEntry::~KlassInfoEntry() { 54 if (_subclasses != NULL) { 55 delete _subclasses; 56 } 57 } 58 675 if (print_stats) { 676 print_class_stats(st, csv_format, columns); 677 } else { 678 st->print_cr(" num #instances #bytes class name (module)"); 679 st->print_cr("-------------------------------------------------------"); 680 print_elements(st); 681 } 682 } 683 684 class HistoClosure : public KlassInfoClosure { 685 private: 686 KlassInfoHisto* _cih; 687 public: 688 HistoClosure(KlassInfoHisto* cih) : _cih(cih) {} 689 690 void do_cinfo(KlassInfoEntry* cie) { 691 _cih->add(cie); 692 } 693 }; 694 695 696 class FindClassByNameClosure : public KlassInfoClosure { 697 private: 698 GrowableArray<Klass*>* _klasses; 699 Symbol* _classname; 700 public: 701 FindClassByNameClosure(GrowableArray<Klass*>* klasses, Symbol* classname) : 702 _klasses(klasses), _classname(classname) { } 703 704 void do_cinfo(KlassInfoEntry* cie) { 705 if (cie->klass()->name() == _classname) { 706 _klasses->append(cie->klass()); 707 } 708 } 709 }; 710 711 class FieldDesc { 712 private: 713 Symbol* _name; 714 Symbol* _signature; 715 int _offset; 716 int _index; 717 InstanceKlass* _holder; 718 AccessFlags _access_flags; 719 public: 720 FieldDesc() { 721 _name = NULL; 722 _signature = NULL; 723 _offset = -1; 724 _index = -1; 725 _holder = NULL; 726 _access_flags = AccessFlags(); 727 } 728 FieldDesc(fieldDescriptor& fd) { 729 _name = fd.name(); 730 _signature = fd.signature(); 731 _offset = fd.offset(); 732 _index = fd.index(); 733 _holder = fd.field_holder(); 734 _access_flags = fd.access_flags(); 735 } 736 Symbol* name() { return _name;} 737 Symbol* signature() { return _signature; } 738 int offset() { return _offset; } 739 int index() { return _index; } 740 InstanceKlass* holder() { return _holder; } 741 AccessFlags access_flags() { return _access_flags; } 742 }; 743 744 static int compare_offset(FieldDesc* f1, FieldDesc* f2) { 745 return f1->offset() > f2->offset() ? 1 : -1; 746 } 747 748 static void print_field(outputStream* st, int level, int offset, FieldDesc& fd, bool flattenable, bool flattened ) { 749 char* flattened_msg = (char*)""; 750 if (flattenable) { 751 flattened_msg = flattened ? (char*)"and flattened" : (char*)"not flattened"; 752 } 753 st->print_cr(" @ %d %*s \"%s\" %s %s %s", 754 offset, level * 3, "", 755 fd.name()->as_C_string(), 756 fd.signature()->as_C_string(), 757 flattenable ? " // flattenable" : "", 758 flattened_msg); 759 } 760 761 static void print_flattened_field(outputStream* st, int level, int offset, InstanceKlass* klass) { 762 assert(klass->is_value(), "Only value classes can be flattened"); 763 ValueKlass* vklass = ValueKlass::cast(klass); 764 GrowableArray<FieldDesc>* fields = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<FieldDesc>(100, true); 765 for (FieldStream fd(klass, false, false); !fd.eos(); fd.next()) { 766 if (!fd.access_flags().is_static()) { 767 fields->append(FieldDesc(fd.field_descriptor())); 768 } 769 } 770 fields->sort(compare_offset); 771 for(int i = 0; i < fields->length(); i++) { 772 FieldDesc fd = fields->at(i); 773 int offset2 = offset + fd.offset() - vklass->first_field_offset(); 774 print_field(st, level, offset2, fd, 775 fd.access_flags().is_flattenable(), fd.holder()->field_is_flattened(fd.index())); 776 if (fd.holder()->field_is_flattened(fd.index())) { 777 print_flattened_field(st, level + 1, offset2 , 778 InstanceKlass::cast(fd.holder()->get_value_field_klass(fd.index()))); 779 } 780 } 781 } 782 783 void PrintClassLayout::print_class_layout(outputStream* st, char* class_name) { 784 KlassInfoTable cit(true); 785 if (cit.allocation_failed()) { 786 st->print_cr("ERROR: Ran out of C-heap; hierarchy not generated"); 787 return; 788 } 789 790 Thread* THREAD = Thread::current(); 791 792 Symbol* classname = SymbolTable::probe(class_name, strlen(class_name)); 793 794 GrowableArray<Klass*>* klasses = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<Klass*>(100, true); 795 796 FindClassByNameClosure fbnc(klasses, classname); 797 cit.iterate(&fbnc); 798 799 for(int i = 0; i < klasses->length(); i++) { 800 Klass* klass = klasses->at(i); 801 if (!klass->is_instance_klass()) continue; // Skip 802 InstanceKlass* ik = InstanceKlass::cast(klass); 803 int tab = 1; 804 st->print_cr("Class %s [@%s]:", klass->name()->as_C_string(), 805 klass->class_loader_data()->name()->as_C_string()); 806 ResourceMark rm; 807 GrowableArray<FieldDesc>* fields = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<FieldDesc>(100, true); 808 for (FieldStream fd(ik, false, false); !fd.eos(); fd.next()) { 809 if (!fd.access_flags().is_static()) { 810 fields->append(FieldDesc(fd.field_descriptor())); 811 } 812 } 813 fields->sort(compare_offset); 814 for(int i = 0; i < fields->length(); i++) { 815 FieldDesc fd = fields->at(i); 816 print_field(st, 0, fd.offset(), fd, fd.access_flags().is_flattenable(), fd.holder()->field_is_flattened(fd.index())); 817 if (fd.holder()->field_is_flattened(fd.index())) { 818 print_flattened_field(st, 1, fd.offset(), 819 InstanceKlass::cast(fd.holder()->get_value_field_klass(fd.index()))); 820 } 821 } 822 } 823 st->cr(); 824 } 825 826 class RecordInstanceClosure : public ObjectClosure { 827 private: 828 KlassInfoTable* _cit; 829 size_t _missed_count; 830 BoolObjectClosure* _filter; 831 public: 832 RecordInstanceClosure(KlassInfoTable* cit, BoolObjectClosure* filter) : 833 _cit(cit), _missed_count(0), _filter(filter) {} 834 835 void do_object(oop obj) { 836 if (should_visit(obj)) { 837 if (!_cit->record_instance(obj)) { 838 _missed_count++; 839 } 840 } 841 } 842 843 size_t missed_count() { return _missed_count; } 844 845 private: |