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 |
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 |