comparison src/share/vm/memory/heapInspection.cpp @ 11:3c1dbcaaab1d

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
author ysr
date Tue, 26 Feb 2008 15:57:49 -0800
parents a61af66fc99e
children d1605aabd0a1 37f87013dfd8
comparison
equal deleted inserted replaced
10:28372612af5e 11:3c1dbcaaab1d
63 if (_klass == Universe::constantPoolCacheKlassObj()) name = "<constantPoolCacheKlass>"; else 63 if (_klass == Universe::constantPoolCacheKlassObj()) name = "<constantPoolCacheKlass>"; else
64 if (_klass == Universe::compiledICHolderKlassObj()) name = "<compiledICHolderKlass>"; else 64 if (_klass == Universe::compiledICHolderKlassObj()) name = "<compiledICHolderKlass>"; else
65 name = "<no name>"; 65 name = "<no name>";
66 } 66 }
67 // simplify the formatting (ILP32 vs LP64) - always cast the numbers to 64-bit 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 (jlong) _instance_count, 69 (jlong) _instance_count,
70 (julong) _instance_words * HeapWordSize, 70 (julong) _instance_words * HeapWordSize,
71 name); 71 name);
72 } 72 }
73 73
78 return elt; 78 return elt;
79 } 79 }
80 elt = elt->next(); 80 elt = elt->next();
81 } 81 }
82 elt = new KlassInfoEntry(k, list()); 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 return elt; 87 return elt;
85 } 88 }
86 89
87 void KlassInfoBucket::iterate(KlassInfoClosure* cic) { 90 void KlassInfoBucket::iterate(KlassInfoClosure* cic) {
88 KlassInfoEntry* elt = _list; 91 KlassInfoEntry* elt = _list;
101 elt = next; 104 elt = next;
102 } 105 }
103 } 106 }
104 107
105 KlassInfoTable::KlassInfoTable(int size, HeapWord* ref) { 108 KlassInfoTable::KlassInfoTable(int size, HeapWord* ref) {
106 _size = size; 109 _size = 0;
107 _ref = ref; 110 _ref = ref;
108 _buckets = NEW_C_HEAP_ARRAY(KlassInfoBucket, _size); 111 _buckets = NEW_C_HEAP_ARRAY(KlassInfoBucket, size);
109 112 if (_buckets != NULL) {
110 for (int index = 0; index < _size; index++) { 113 _size = size;
111 _buckets[index].initialize(); 114 for (int index = 0; index < _size; index++) {
115 _buckets[index].initialize();
116 }
112 } 117 }
113 } 118 }
114 119
115 KlassInfoTable::~KlassInfoTable() { 120 KlassInfoTable::~KlassInfoTable() {
116 for (int index = 0; index < _size; index++) { 121 if (_buckets != NULL) {
117 _buckets[index].empty(); 122 for (int index = 0; index < _size; index++) {
118 } 123 _buckets[index].empty();
119 FREE_C_HEAP_ARRAY(KlassInfoBucket, _buckets); 124 }
120 _size = 0; 125 FREE_C_HEAP_ARRAY(KlassInfoBucket, _buckets);
126 _size = 0;
127 }
121 } 128 }
122 129
123 uint KlassInfoTable::hash(klassOop p) { 130 uint KlassInfoTable::hash(klassOop p) {
124 assert(Universe::heap()->is_in_permanent((HeapWord*)p), "all klasses in permgen"); 131 assert(Universe::heap()->is_in_permanent((HeapWord*)p), "all klasses in permgen");
125 return (uint)(((uintptr_t)p - (uintptr_t)_ref) >> 2); 132 return (uint)(((uintptr_t)p - (uintptr_t)_ref) >> 2);
126 } 133 }
127 134
128 KlassInfoEntry* KlassInfoTable::lookup(const klassOop k) { 135 KlassInfoEntry* KlassInfoTable::lookup(const klassOop k) {
129 uint idx = hash(k) % _size; 136 uint idx = hash(k) % _size;
137 assert(_buckets != NULL, "Allocation failure should have been caught");
130 KlassInfoEntry* e = _buckets[idx].lookup(k); 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 return e; 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 klassOop k = obj->klass(); 148 klassOop k = obj->klass();
137 KlassInfoEntry* elt = lookup(k); 149 KlassInfoEntry* elt = lookup(k);
138 elt->set_count(elt->count() + 1); 150 // elt may be NULL if it's a new klass for which we
139 elt->set_words(elt->words() + obj->size()); 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 void KlassInfoTable::iterate(KlassInfoClosure* cic) { 161 void KlassInfoTable::iterate(KlassInfoClosure* cic) {
162 assert(_size == 0 || _buckets != NULL, "Allocation failure should have been caught");
143 for (int index = 0; index < _size; index++) { 163 for (int index = 0; index < _size; index++) {
144 _buckets[index].iterate(cic); 164 _buckets[index].iterate(cic);
145 } 165 }
146 } 166 }
147 167
174 st->print("%4d: ", i+1); 194 st->print("%4d: ", i+1);
175 elements()->at(i)->print_on(st); 195 elements()->at(i)->print_on(st);
176 total += elements()->at(i)->count(); 196 total += elements()->at(i)->count();
177 totalw += elements()->at(i)->words(); 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 total, totalw * HeapWordSize); 200 total, totalw * HeapWordSize);
181 } 201 }
182 202
183 void KlassInfoHisto::print_on(outputStream* st) const { 203 void KlassInfoHisto::print_on(outputStream* st) const {
184 st->print_cr("%s",title()); 204 st->print_cr("%s",title());
197 }; 217 };
198 218
199 class RecordInstanceClosure : public ObjectClosure { 219 class RecordInstanceClosure : public ObjectClosure {
200 private: 220 private:
201 KlassInfoTable* _cit; 221 KlassInfoTable* _cit;
222 size_t _missed_count;
202 public: 223 public:
203 RecordInstanceClosure(KlassInfoTable* cit) : _cit(cit) {} 224 RecordInstanceClosure(KlassInfoTable* cit) :
225 _cit(cit), _missed_count(0) {}
204 226
205 void do_object(oop obj) { 227 void do_object(oop obj) {
206 _cit->record_instance(obj); 228 if (!_cit->record_instance(obj)) {
207 } 229 _missed_count++;
230 }
231 }
232
233 size_t missed_count() { return _missed_count; }
208 }; 234 };
209 235
210 void HeapInspection::heap_inspection(outputStream* st) { 236 void HeapInspection::heap_inspection(outputStream* st) {
211 ResourceMark rm; 237 ResourceMark rm;
212 HeapWord* ref; 238 HeapWord* ref;
228 #endif // SERIALGC 254 #endif // SERIALGC
229 default: 255 default:
230 ShouldNotReachHere(); // Unexpected heap kind for this op 256 ShouldNotReachHere(); // Unexpected heap kind for this op
231 } 257 }
232 // Collect klass instance info 258 // Collect klass instance info
233
234 // Iterate over objects in the heap
235 KlassInfoTable cit(KlassInfoTable::cit_size, ref); 259 KlassInfoTable cit(KlassInfoTable::cit_size, ref);
236 RecordInstanceClosure ric(&cit); 260 if (!cit.allocation_failed()) {
237 Universe::heap()->object_iterate(&ric); 261 // Iterate over objects in the heap
238 262 RecordInstanceClosure ric(&cit);
239 // Sort and print klass instance info 263 Universe::heap()->object_iterate(&ric);
240 KlassInfoHisto histo("\n" 264
241 " num #instances #bytes class name\n" 265 // Report if certain classes are not counted because of
242 "----------------------------------------------", 266 // running out of C-heap for the histogram.
243 KlassInfoHisto::histo_initial_size); 267 size_t missed_count = ric.missed_count();
244 HistoClosure hc(&histo); 268 if (missed_count != 0) {
245 cit.iterate(&hc); 269 st->print_cr("WARNING: Ran out of C-heap; undercounted " SIZE_FORMAT
246 histo.sort(); 270 " total instances in data below",
247 histo.print_on(st); 271 missed_count);
272 }
273 // Sort and print klass instance info
274 KlassInfoHisto histo("\n"
275 " num #instances #bytes class name\n"
276 "----------------------------------------------",
277 KlassInfoHisto::histo_initial_size);
278 HistoClosure hc(&histo);
279 cit.iterate(&hc);
280 histo.sort();
281 histo.print_on(st);
282 } else {
283 st->print_cr("WARNING: Ran out of C-heap; histogram not generated");
284 }
248 st->flush(); 285 st->flush();
249 286
250 if (Universe::heap()->kind() == CollectedHeap::GenCollectedHeap) { 287 if (Universe::heap()->kind() == CollectedHeap::GenCollectedHeap) {
251 GenCollectedHeap* gch = GenCollectedHeap::heap(); 288 GenCollectedHeap* gch = GenCollectedHeap::heap();
252 gch->gc_epilogue(false /* !full */); // release all acquired locks 289 gch->gc_epilogue(false /* !full */); // release all acquired locks