6621728: Heap inspection should not crash in the face of C-heap exhaustion

Tue, 26 Feb 2008 15:57:49 -0800

author
ysr
date
Tue, 26 Feb 2008 15:57:49 -0800
changeset 446
3c1dbcaaab1d
parent 445
28372612af5e
child 447
6432c3bb6240

6621728: Heap inspection should not crash in the face of C-heap exhaustion
Summary: Deal more gracefully with situations where C-heap scratch space cannot be had
Reviewed-by: jmasa

src/share/vm/memory/heapInspection.cpp file | annotate | diff | comparison | revisions
src/share/vm/memory/heapInspection.hpp file | annotate | diff | comparison | revisions
     1.1 --- a/src/share/vm/memory/heapInspection.cpp	Fri Feb 22 17:17:14 2008 -0800
     1.2 +++ b/src/share/vm/memory/heapInspection.cpp	Tue Feb 26 15:57:49 2008 -0800
     1.3 @@ -65,7 +65,7 @@
     1.4        name = "<no name>";
     1.5    }
     1.6    // simplify the formatting (ILP32 vs LP64) - always cast the numbers to 64-bit
     1.7 -  st->print_cr("%13" FORMAT64_MODIFIER "d  %13" FORMAT64_MODIFIER "u  %s",
     1.8 +  st->print_cr(INT64_FORMAT_W(13) "  " UINT64_FORMAT_W(13) "  %s",
     1.9                 (jlong)  _instance_count,
    1.10                 (julong) _instance_words * HeapWordSize,
    1.11                 name);
    1.12 @@ -80,7 +80,10 @@
    1.13      elt = elt->next();
    1.14    }
    1.15    elt = new KlassInfoEntry(k, list());
    1.16 -  set_list(elt);
    1.17 +  // We may be out of space to allocate the new entry.
    1.18 +  if (elt != NULL) {
    1.19 +    set_list(elt);
    1.20 +  }
    1.21    return elt;
    1.22  }
    1.23  
    1.24 @@ -103,21 +106,25 @@
    1.25  }
    1.26  
    1.27  KlassInfoTable::KlassInfoTable(int size, HeapWord* ref) {
    1.28 -  _size = size;
    1.29 +  _size = 0;
    1.30    _ref = ref;
    1.31 -  _buckets = NEW_C_HEAP_ARRAY(KlassInfoBucket, _size);
    1.32 -
    1.33 -  for (int index = 0; index < _size; index++) {
    1.34 -    _buckets[index].initialize();
    1.35 +  _buckets = NEW_C_HEAP_ARRAY(KlassInfoBucket, size);
    1.36 +  if (_buckets != NULL) {
    1.37 +    _size = size;
    1.38 +    for (int index = 0; index < _size; index++) {
    1.39 +      _buckets[index].initialize();
    1.40 +    }
    1.41    }
    1.42  }
    1.43  
    1.44  KlassInfoTable::~KlassInfoTable() {
    1.45 -  for (int index = 0; index < _size; index++) {
    1.46 -    _buckets[index].empty();
    1.47 +  if (_buckets != NULL) {
    1.48 +    for (int index = 0; index < _size; index++) {
    1.49 +      _buckets[index].empty();
    1.50 +    }
    1.51 +    FREE_C_HEAP_ARRAY(KlassInfoBucket, _buckets);
    1.52 +    _size = 0;
    1.53    }
    1.54 -  FREE_C_HEAP_ARRAY(KlassInfoBucket, _buckets);
    1.55 -  _size = 0;
    1.56  }
    1.57  
    1.58  uint KlassInfoTable::hash(klassOop p) {
    1.59 @@ -127,19 +134,32 @@
    1.60  
    1.61  KlassInfoEntry* KlassInfoTable::lookup(const klassOop k) {
    1.62    uint         idx = hash(k) % _size;
    1.63 +  assert(_buckets != NULL, "Allocation failure should have been caught");
    1.64    KlassInfoEntry*  e   = _buckets[idx].lookup(k);
    1.65 -  assert(k == e->klass(), "must be equal");
    1.66 +  // Lookup may fail if this is a new klass for which we
    1.67 +  // could not allocate space for an new entry.
    1.68 +  assert(e == NULL || k == e->klass(), "must be equal");
    1.69    return e;
    1.70  }
    1.71  
    1.72 -void KlassInfoTable::record_instance(const oop obj) {
    1.73 +// Return false if the entry could not be recorded on account
    1.74 +// of running out of space required to create a new entry.
    1.75 +bool KlassInfoTable::record_instance(const oop obj) {
    1.76    klassOop      k = obj->klass();
    1.77    KlassInfoEntry* elt = lookup(k);
    1.78 -  elt->set_count(elt->count() + 1);
    1.79 -  elt->set_words(elt->words() + obj->size());
    1.80 +  // elt may be NULL if it's a new klass for which we
    1.81 +  // could not allocate space for a new entry in the hashtable.
    1.82 +  if (elt != NULL) {
    1.83 +    elt->set_count(elt->count() + 1);
    1.84 +    elt->set_words(elt->words() + obj->size());
    1.85 +    return true;
    1.86 +  } else {
    1.87 +    return false;
    1.88 +  }
    1.89  }
    1.90  
    1.91  void KlassInfoTable::iterate(KlassInfoClosure* cic) {
    1.92 +  assert(_size == 0 || _buckets != NULL, "Allocation failure should have been caught");
    1.93    for (int index = 0; index < _size; index++) {
    1.94      _buckets[index].iterate(cic);
    1.95    }
    1.96 @@ -176,7 +196,7 @@
    1.97      total += elements()->at(i)->count();
    1.98      totalw += elements()->at(i)->words();
    1.99    }
   1.100 -  st->print_cr("Total %13" FORMAT64_MODIFIER "d  %13" FORMAT64_MODIFIER "u",
   1.101 +  st->print_cr("Total " INT64_FORMAT_W(13) "  " UINT64_FORMAT_W(13),
   1.102                 total, totalw * HeapWordSize);
   1.103  }
   1.104  
   1.105 @@ -199,12 +219,18 @@
   1.106  class RecordInstanceClosure : public ObjectClosure {
   1.107   private:
   1.108    KlassInfoTable* _cit;
   1.109 +  size_t _missed_count;
   1.110   public:
   1.111 -  RecordInstanceClosure(KlassInfoTable* cit) : _cit(cit) {}
   1.112 +  RecordInstanceClosure(KlassInfoTable* cit) :
   1.113 +    _cit(cit), _missed_count(0) {}
   1.114  
   1.115    void do_object(oop obj) {
   1.116 -    _cit->record_instance(obj);
   1.117 +    if (!_cit->record_instance(obj)) {
   1.118 +      _missed_count++;
   1.119 +    }
   1.120    }
   1.121 +
   1.122 +  size_t missed_count() { return _missed_count; }
   1.123  };
   1.124  
   1.125  void HeapInspection::heap_inspection(outputStream* st) {
   1.126 @@ -230,21 +256,32 @@
   1.127        ShouldNotReachHere(); // Unexpected heap kind for this op
   1.128    }
   1.129    // Collect klass instance info
   1.130 +  KlassInfoTable cit(KlassInfoTable::cit_size, ref);
   1.131 +  if (!cit.allocation_failed()) {
   1.132 +    // Iterate over objects in the heap
   1.133 +    RecordInstanceClosure ric(&cit);
   1.134 +    Universe::heap()->object_iterate(&ric);
   1.135  
   1.136 -  // Iterate over objects in the heap
   1.137 -  KlassInfoTable cit(KlassInfoTable::cit_size, ref);
   1.138 -  RecordInstanceClosure ric(&cit);
   1.139 -  Universe::heap()->object_iterate(&ric);
   1.140 -
   1.141 -  // Sort and print klass instance info
   1.142 -  KlassInfoHisto histo("\n"
   1.143 -                   " num     #instances         #bytes  class name\n"
   1.144 -                   "----------------------------------------------",
   1.145 -                   KlassInfoHisto::histo_initial_size);
   1.146 -  HistoClosure hc(&histo);
   1.147 -  cit.iterate(&hc);
   1.148 -  histo.sort();
   1.149 -  histo.print_on(st);
   1.150 +    // Report if certain classes are not counted because of
   1.151 +    // running out of C-heap for the histogram.
   1.152 +    size_t missed_count = ric.missed_count();
   1.153 +    if (missed_count != 0) {
   1.154 +      st->print_cr("WARNING: Ran out of C-heap; undercounted " SIZE_FORMAT
   1.155 +                   " total instances in data below",
   1.156 +                   missed_count);
   1.157 +    }
   1.158 +    // Sort and print klass instance info
   1.159 +    KlassInfoHisto histo("\n"
   1.160 +                     " num     #instances         #bytes  class name\n"
   1.161 +                     "----------------------------------------------",
   1.162 +                     KlassInfoHisto::histo_initial_size);
   1.163 +    HistoClosure hc(&histo);
   1.164 +    cit.iterate(&hc);
   1.165 +    histo.sort();
   1.166 +    histo.print_on(st);
   1.167 +  } else {
   1.168 +    st->print_cr("WARNING: Ran out of C-heap; histogram not generated");
   1.169 +  }
   1.170    st->flush();
   1.171  
   1.172    if (Universe::heap()->kind() == CollectedHeap::GenCollectedHeap) {
     2.1 --- a/src/share/vm/memory/heapInspection.hpp	Fri Feb 22 17:17:14 2008 -0800
     2.2 +++ b/src/share/vm/memory/heapInspection.hpp	Tue Feb 26 15:57:49 2008 -0800
     2.3 @@ -98,8 +98,9 @@
     2.4    };
     2.5    KlassInfoTable(int size, HeapWord* ref);
     2.6    ~KlassInfoTable();
     2.7 -  void record_instance(const oop obj);
     2.8 +  bool record_instance(const oop obj);
     2.9    void iterate(KlassInfoClosure* cic);
    2.10 +  bool allocation_failed() { return _buckets == NULL; }
    2.11  };
    2.12  
    2.13  class KlassInfoHisto : public StackObj {

mercurial