1 /*
   2  * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  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 #ifndef SHARE_MEMORY_HEAPINSPECTION_HPP
  26 #define SHARE_MEMORY_HEAPINSPECTION_HPP
  27 
  28 #include "memory/allocation.hpp"
  29 #include "oops/objArrayOop.hpp"
  30 #include "oops/oop.hpp"
  31 #include "oops/annotations.hpp"
  32 #include "utilities/macros.hpp"
  33 
  34 #if INCLUDE_SERVICES
  35 
  36 
  37 // HeapInspection
  38 
  39 // KlassInfoTable is a bucket hash table that
  40 // maps Klass*s to extra information:
  41 //    instance count and instance word size.
  42 //
  43 // A KlassInfoBucket is the head of a link list
  44 // of KlassInfoEntry's
  45 //
  46 // KlassInfoHisto is a growable array of pointers
  47 // to KlassInfoEntry's and is used to sort
  48 // the entries.
  49 
  50 class KlassInfoEntry: public CHeapObj<mtInternal> {
  51  private:
  52   KlassInfoEntry* _next;
  53   Klass*          _klass;
  54   long            _instance_count;
  55   size_t          _instance_words;
  56   long            _index;
  57   bool            _do_print; // True if we should print this class when printing the class hierarchy.
  58   GrowableArray<KlassInfoEntry*>* _subclasses;
  59 
  60  public:
  61   KlassInfoEntry(Klass* k, KlassInfoEntry* next) :
  62     _next(next), _klass(k), _instance_count(0), _instance_words(0), _index(-1),
  63     _do_print(false), _subclasses(NULL)
  64   {}
  65   ~KlassInfoEntry();
  66   KlassInfoEntry* next() const   { return _next; }
  67   bool is_equal(const Klass* k)  { return k == _klass; }
  68   Klass* klass()  const      { return _klass; }
  69   long count()    const      { return _instance_count; }
  70   void set_count(long ct)    { _instance_count = ct; }
  71   size_t words()  const      { return _instance_words; }
  72   void set_words(size_t wds) { _instance_words = wds; }
  73   void set_index(long index) { _index = index; }
  74   long index()    const      { return _index; }
  75   GrowableArray<KlassInfoEntry*>* subclasses() const { return _subclasses; }
  76   void add_subclass(KlassInfoEntry* cie);
  77   void set_do_print(bool do_print) { _do_print = do_print; }
  78   bool do_print() const      { return _do_print; }
  79   int compare(KlassInfoEntry* e1, KlassInfoEntry* e2);
  80   void print_on(outputStream* st) const;
  81   const char* name() const;
  82 };
  83 
  84 class KlassInfoClosure : public StackObj {
  85  public:
  86   // Called for each KlassInfoEntry.
  87   virtual void do_cinfo(KlassInfoEntry* cie) = 0;
  88 };
  89 
  90 class KlassInfoBucket: public CHeapObj<mtInternal> {
  91  private:
  92   KlassInfoEntry* _list;
  93   KlassInfoEntry* list()           { return _list; }
  94   void set_list(KlassInfoEntry* l) { _list = l; }
  95  public:
  96   KlassInfoEntry* lookup(Klass* k);
  97   void initialize() { _list = NULL; }
  98   void empty();
  99   void iterate(KlassInfoClosure* cic);
 100 };
 101 
 102 class KlassInfoTable: public StackObj {
 103  private:
 104   static const int _num_buckets = 20011;
 105   size_t _size_of_instances_in_words;
 106 
 107   // An aligned reference address (typically the least
 108   // address in the perm gen) used for hashing klass
 109   // objects.
 110   HeapWord* _ref;
 111 
 112   KlassInfoBucket* _buckets;
 113   uint hash(const Klass* p);
 114   KlassInfoEntry* lookup(Klass* k); // allocates if not found!
 115 
 116   class AllClassesFinder;
 117 
 118  public:
 119   KlassInfoTable(bool add_all_classes);
 120   ~KlassInfoTable();
 121   bool record_instance(const oop obj);
 122   void iterate(KlassInfoClosure* cic);
 123   bool allocation_failed() { return _buckets == NULL; }
 124   size_t size_of_instances_in_words() const;
 125 
 126   friend class KlassInfoHisto;
 127   friend class KlassHierarchy;
 128 };
 129 
 130 class KlassHierarchy : AllStatic {
 131  public:
 132   static void print_class_hierarchy(outputStream* st, bool print_interfaces,  bool print_subclasses,
 133                                     char* classname);
 134 
 135  private:
 136   static void set_do_print_for_class_hierarchy(KlassInfoEntry* cie, KlassInfoTable* cit,
 137                                                bool print_subclasse);
 138   static void print_class(outputStream* st, KlassInfoEntry* cie, bool print_subclasses);
 139 };
 140 
 141 class KlassInfoHisto : public StackObj {
 142  private:
 143   static const int _histo_initial_size = 1000;
 144   KlassInfoTable *_cit;
 145   GrowableArray<KlassInfoEntry*>* _elements;
 146   GrowableArray<KlassInfoEntry*>* elements() const { return _elements; }
 147   static int sort_helper(KlassInfoEntry** e1, KlassInfoEntry** e2);
 148   void print_elements(outputStream* st) const;
 149   bool is_selected(const char *col_name);
 150 
 151   template <class T> static int count_bytes(T* x) {
 152     return (HeapWordSize * ((x) ? (x)->size() : 0));
 153   }
 154 
 155   template <class T> static int count_bytes_array(T* x) {
 156     if (x == NULL) {
 157       return 0;
 158     }
 159     if (x->length() == 0) {
 160       // This is a shared array, e.g., Universe::the_empty_int_array(). Don't
 161       // count it to avoid double-counting.
 162       return 0;
 163     }
 164     return HeapWordSize * x->size();
 165   }
 166 
 167   static void print_julong(outputStream* st, int width, julong n) {
 168     int num_spaces = width - julong_width(n);
 169     if (num_spaces > 0) {
 170       st->print("%*s", num_spaces, "");
 171     }
 172     st->print(JULONG_FORMAT, n);
 173   }
 174 
 175   static int julong_width(julong n) {
 176     if (n == 0) {
 177       return 1;
 178     }
 179     int w = 0;
 180     while (n > 0) {
 181       n /= 10;
 182       w += 1;
 183     }
 184     return w;
 185   }
 186 
 187   static int col_width(julong n, const char *name) {
 188     int w = julong_width(n);
 189     int min = (int)(strlen(name));
 190     if (w < min) {
 191         w = min;
 192     }
 193     // add a leading space for separation.
 194     return w + 1;
 195   }
 196 
 197  public:
 198   KlassInfoHisto(KlassInfoTable* cit);
 199   ~KlassInfoHisto();
 200   void add(KlassInfoEntry* cie);
 201   void print_histo_on(outputStream* st);
 202   void sort();
 203 };
 204 
 205 #endif // INCLUDE_SERVICES
 206 
 207 // These declarations are needed since the declaration of KlassInfoTable and
 208 // KlassInfoClosure are guarded by #if INLCUDE_SERVICES
 209 class KlassInfoTable;
 210 class KlassInfoClosure;
 211 
 212 class HeapInspection : public StackObj {
 213  public:
 214   void heap_inspection(outputStream* st) NOT_SERVICES_RETURN;
 215   size_t populate_table(KlassInfoTable* cit, BoolObjectClosure* filter = NULL) NOT_SERVICES_RETURN_(0);
 216   static void find_instances_at_safepoint(Klass* k, GrowableArray<oop>* result) NOT_SERVICES_RETURN;
 217  private:
 218   void iterate_over_heap(KlassInfoTable* cit, BoolObjectClosure* filter = NULL);
 219 };
 220 
 221 #endif // SHARE_MEMORY_HEAPINSPECTION_HPP