Mercurial > hg > graal-compiler
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 |