Print this page


Split Split Close
Expand all
Collapse all
          --- old/src/share/vm/memory/heapInspection.cpp
          +++ new/src/share/vm/memory/heapInspection.cpp
↓ open down ↓ 57 lines elided ↑ open up ↑
  58   58      if (_klass == Universe::longArrayKlassObj())         name = "<longArrayKlass>";         else
  59   59      if (_klass == Universe::methodKlassObj())            name = "<methodKlass>";            else
  60   60      if (_klass == Universe::constMethodKlassObj())       name = "<constMethodKlass>";       else
  61   61      if (_klass == Universe::methodDataKlassObj())        name = "<methodDataKlass>";        else
  62   62      if (_klass == Universe::constantPoolKlassObj())      name = "<constantPoolKlass>";      else
  63   63      if (_klass == Universe::constantPoolCacheKlassObj()) name = "<constantPoolCacheKlass>"; else
  64   64      if (_klass == Universe::compiledICHolderKlassObj())  name = "<compiledICHolderKlass>";  else
  65   65        name = "<no name>";
  66   66    }
  67   67    // simplify the formatting (ILP32 vs LP64) - always cast the numbers to 64-bit
  68      -  st->print_cr("%13" FORMAT64_MODIFIER "d  %13" FORMAT64_MODIFIER "u  %s",
       68 +  st->print_cr(INT64_FORMAT_W(13) "  " UINT64_FORMAT_W(13) "  %s",
  69   69                 (jlong)  _instance_count,
  70   70                 (julong) _instance_words * HeapWordSize,
  71   71                 name);
  72   72  }
  73   73  
  74   74  KlassInfoEntry* KlassInfoBucket::lookup(const klassOop k) {
  75   75    KlassInfoEntry* elt = _list;
  76   76    while (elt != NULL) {
  77   77      if (elt->is_equal(k)) {
  78   78        return elt;
  79   79      }
  80   80      elt = elt->next();
  81   81    }
  82   82    elt = new KlassInfoEntry(k, list());
  83      -  set_list(elt);
       83 +  // We may be out of space to allocate the new entry.
       84 +  if (elt != NULL) {
       85 +    set_list(elt);
       86 +  }
  84   87    return elt;
  85   88  }
  86   89  
  87   90  void KlassInfoBucket::iterate(KlassInfoClosure* cic) {
  88   91    KlassInfoEntry* elt = _list;
  89   92    while (elt != NULL) {
  90   93      cic->do_cinfo(elt);
  91   94      elt = elt->next();
  92   95    }
  93   96  }
↓ open down ↓ 2 lines elided ↑ open up ↑
  96   99    KlassInfoEntry* elt = _list;
  97  100    _list = NULL;
  98  101    while (elt != NULL) {
  99  102      KlassInfoEntry* next = elt->next();
 100  103      delete elt;
 101  104      elt = next;
 102  105    }
 103  106  }
 104  107  
 105  108  KlassInfoTable::KlassInfoTable(int size, HeapWord* ref) {
 106      -  _size = size;
      109 +  _size = 0;
 107  110    _ref = ref;
 108      -  _buckets = NEW_C_HEAP_ARRAY(KlassInfoBucket, _size);
 109      -
 110      -  for (int index = 0; index < _size; index++) {
 111      -    _buckets[index].initialize();
      111 +  _buckets = NEW_C_HEAP_ARRAY(KlassInfoBucket, size);
      112 +  if (_buckets != NULL) {
      113 +    _size = size;
      114 +    for (int index = 0; index < _size; index++) {
      115 +      _buckets[index].initialize();
      116 +    }
 112  117    }
 113  118  }
 114  119  
 115  120  KlassInfoTable::~KlassInfoTable() {
 116      -  for (int index = 0; index < _size; index++) {
 117      -    _buckets[index].empty();
      121 +  if (_buckets != NULL) {
      122 +    for (int index = 0; index < _size; index++) {
      123 +      _buckets[index].empty();
      124 +    }
      125 +    FREE_C_HEAP_ARRAY(KlassInfoBucket, _buckets);
      126 +    _size = 0;
 118  127    }
 119      -  FREE_C_HEAP_ARRAY(KlassInfoBucket, _buckets);
 120      -  _size = 0;
 121  128  }
 122  129  
 123  130  uint KlassInfoTable::hash(klassOop p) {
 124  131    assert(Universe::heap()->is_in_permanent((HeapWord*)p), "all klasses in permgen");
 125  132    return (uint)(((uintptr_t)p - (uintptr_t)_ref) >> 2);
 126  133  }
 127  134  
 128  135  KlassInfoEntry* KlassInfoTable::lookup(const klassOop k) {
 129  136    uint         idx = hash(k) % _size;
      137 +  assert(_buckets != NULL, "Allocation failure should have been caught");
 130  138    KlassInfoEntry*  e   = _buckets[idx].lookup(k);
 131      -  assert(k == e->klass(), "must be equal");
      139 +  // Lookup may fail if this is a new klass for which we
      140 +  // could not allocate space for an new entry.
      141 +  assert(e == NULL || k == e->klass(), "must be equal");
 132  142    return e;
 133  143  }
 134  144  
 135      -void KlassInfoTable::record_instance(const oop obj) {
      145 +// Return false if the entry could not be recorded on account
      146 +// of running out of space required to create a new entry.
      147 +bool KlassInfoTable::record_instance(const oop obj) {
 136  148    klassOop      k = obj->klass();
 137  149    KlassInfoEntry* elt = lookup(k);
 138      -  elt->set_count(elt->count() + 1);
 139      -  elt->set_words(elt->words() + obj->size());
      150 +  // elt may be NULL if it's a new klass for which we
      151 +  // could not allocate space for a new entry in the hashtable.
      152 +  if (elt != NULL) {
      153 +    elt->set_count(elt->count() + 1);
      154 +    elt->set_words(elt->words() + obj->size());
      155 +    return true;
      156 +  } else {
      157 +    return false;
      158 +  }
 140  159  }
 141  160  
 142  161  void KlassInfoTable::iterate(KlassInfoClosure* cic) {
      162 +  assert(_size == 0 || _buckets != NULL, "Allocation failure should have been caught");
 143  163    for (int index = 0; index < _size; index++) {
 144  164      _buckets[index].iterate(cic);
 145  165    }
 146  166  }
 147  167  
 148  168  int KlassInfoHisto::sort_helper(KlassInfoEntry** e1, KlassInfoEntry** e2) {
 149  169    return (*e1)->compare(*e1,*e2);
 150  170  }
 151  171  
 152  172  KlassInfoHisto::KlassInfoHisto(const char* title, int estimatedCount) :
↓ open down ↓ 16 lines elided ↑ open up ↑
 169  189  void KlassInfoHisto::print_elements(outputStream* st) const {
 170  190    // simplify the formatting (ILP32 vs LP64) - store the sum in 64-bit
 171  191    jlong total = 0;
 172  192    julong totalw = 0;
 173  193    for(int i=0; i < elements()->length(); i++) {
 174  194      st->print("%4d: ", i+1);
 175  195      elements()->at(i)->print_on(st);
 176  196      total += elements()->at(i)->count();
 177  197      totalw += elements()->at(i)->words();
 178  198    }
 179      -  st->print_cr("Total %13" FORMAT64_MODIFIER "d  %13" FORMAT64_MODIFIER "u",
      199 +  st->print_cr("Total " INT64_FORMAT_W(13) "  " UINT64_FORMAT_W(13),
 180  200                 total, totalw * HeapWordSize);
 181  201  }
 182  202  
 183  203  void KlassInfoHisto::print_on(outputStream* st) const {
 184  204    st->print_cr("%s",title());
 185  205    print_elements(st);
 186  206  }
 187  207  
 188  208  class HistoClosure : public KlassInfoClosure {
 189  209   private:
↓ open down ↓ 2 lines elided ↑ open up ↑
 192  212    HistoClosure(KlassInfoHisto* cih) : _cih(cih) {}
 193  213  
 194  214    void do_cinfo(KlassInfoEntry* cie) {
 195  215      _cih->add(cie);
 196  216    }
 197  217  };
 198  218  
 199  219  class RecordInstanceClosure : public ObjectClosure {
 200  220   private:
 201  221    KlassInfoTable* _cit;
      222 +  size_t _missed_count;
 202  223   public:
 203      -  RecordInstanceClosure(KlassInfoTable* cit) : _cit(cit) {}
      224 +  RecordInstanceClosure(KlassInfoTable* cit) :
      225 +    _cit(cit), _missed_count(0) {}
 204  226  
 205  227    void do_object(oop obj) {
 206      -    _cit->record_instance(obj);
      228 +    if (!_cit->record_instance(obj)) {
      229 +      _missed_count++;
      230 +    }
 207  231    }
      232 +
      233 +  size_t missed_count() { return _missed_count; }
 208  234  };
 209  235  
 210  236  void HeapInspection::heap_inspection(outputStream* st) {
 211  237    ResourceMark rm;
 212  238    HeapWord* ref;
 213  239  
 214  240    CollectedHeap* heap = Universe::heap();
 215  241    switch (heap->kind()) {
 216  242      case CollectedHeap::GenCollectedHeap: {
 217  243        GenCollectedHeap* gch = (GenCollectedHeap*)heap;
↓ open down ↓ 5 lines elided ↑ open up ↑
 223  249      case CollectedHeap::ParallelScavengeHeap: {
 224  250        ParallelScavengeHeap* psh = (ParallelScavengeHeap*)heap;
 225  251        ref = psh->perm_gen()->object_space()->used_region().start();
 226  252        break;
 227  253      }
 228  254  #endif // SERIALGC
 229  255      default:
 230  256        ShouldNotReachHere(); // Unexpected heap kind for this op
 231  257    }
 232  258    // Collect klass instance info
 233      -
 234      -  // Iterate over objects in the heap
 235  259    KlassInfoTable cit(KlassInfoTable::cit_size, ref);
 236      -  RecordInstanceClosure ric(&cit);
 237      -  Universe::heap()->object_iterate(&ric);
 238      -
 239      -  // Sort and print klass instance info
 240      -  KlassInfoHisto histo("\n"
 241      -                   " num     #instances         #bytes  class name\n"
 242      -                   "----------------------------------------------",
 243      -                   KlassInfoHisto::histo_initial_size);
 244      -  HistoClosure hc(&histo);
 245      -  cit.iterate(&hc);
 246      -  histo.sort();
 247      -  histo.print_on(st);
      260 +  if (!cit.allocation_failed()) {
      261 +    // Iterate over objects in the heap
      262 +    RecordInstanceClosure ric(&cit);
      263 +    Universe::heap()->object_iterate(&ric);
      264 +  
      265 +    // Report if certain classes are not counted because of
      266 +    // running out of C-heap for the histogram.
      267 +    size_t missed_count = ric.missed_count();
      268 +    if (missed_count != 0) {
      269 +      st->print_cr("WARNING: Ran out of C-heap; undercounted " SIZE_FORMAT " instances in data below",
      270 +                   missed_count);
      271 +    }
      272 +    // Sort and print klass instance info
      273 +    KlassInfoHisto histo("\n"
      274 +                     " num     #instances         #bytes  class name\n"
      275 +                     "----------------------------------------------",
      276 +                     KlassInfoHisto::histo_initial_size);
      277 +    HistoClosure hc(&histo);
      278 +    cit.iterate(&hc);
      279 +    histo.sort();
      280 +    histo.print_on(st);
      281 +  } else {
      282 +    st->print_cr("WARNING: Ran out of C-heap; histogram not generated");
      283 +  }
 248  284    st->flush();
 249  285  
 250  286    if (Universe::heap()->kind() == CollectedHeap::GenCollectedHeap) {
 251  287      GenCollectedHeap* gch = GenCollectedHeap::heap();
 252  288      gch->gc_epilogue(false /* !full */); // release all acquired locks
 253  289    }
 254  290  }
 255  291  
 256  292  class FindInstanceClosure : public ObjectClosure {
 257  293   private:
↓ open down ↓ 24 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX