Print this page
Split |
Split |
Close |
Expand all |
Collapse all |
--- old/src/share/vm/memory/heapInspection.cpp
+++ new/src/share/vm/memory/heapInspection.cpp
1 1 /*
2 2 * Copyright 2002-2007 Sun Microsystems, Inc. All Rights Reserved.
3 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 4 *
5 5 * This code is free software; you can redistribute it and/or modify it
6 6 * under the terms of the GNU General Public License version 2 only, as
7 7 * published by the Free Software Foundation.
8 8 *
9 9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 12 * version 2 for more details (a copy is included in the LICENSE file that
13 13 * accompanied this code).
14 14 *
15 15 * You should have received a copy of the GNU General Public License version
16 16 * 2 along with this work; if not, write to the Free Software Foundation,
17 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 18 *
19 19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
20 20 * CA 95054 USA or visit www.sun.com if you need additional information or
21 21 * have any questions.
22 22 *
23 23 */
24 24
25 25 # include "incls/_precompiled.incl"
26 26 # include "incls/_heapInspection.cpp.incl"
27 27
28 28 // HeapInspection
29 29
30 30 int KlassInfoEntry::compare(KlassInfoEntry* e1, KlassInfoEntry* e2) {
31 31 if(e1->_instance_words > e2->_instance_words) {
32 32 return -1;
33 33 } else if(e1->_instance_words < e2->_instance_words) {
34 34 return 1;
35 35 }
36 36 return 0;
37 37 }
38 38
39 39 void KlassInfoEntry::print_on(outputStream* st) const {
40 40 ResourceMark rm;
41 41 const char* name;;
42 42 if (_klass->klass_part()->name() != NULL) {
43 43 name = _klass->klass_part()->external_name();
44 44 } else {
45 45 if (_klass == Universe::klassKlassObj()) name = "<klassKlass>"; else
46 46 if (_klass == Universe::arrayKlassKlassObj()) name = "<arrayKlassKlass>"; else
47 47 if (_klass == Universe::objArrayKlassKlassObj()) name = "<objArrayKlassKlass>"; else
48 48 if (_klass == Universe::instanceKlassKlassObj()) name = "<instanceKlassKlass>"; else
49 49 if (_klass == Universe::typeArrayKlassKlassObj()) name = "<typeArrayKlassKlass>"; else
50 50 if (_klass == Universe::symbolKlassObj()) name = "<symbolKlass>"; else
51 51 if (_klass == Universe::boolArrayKlassObj()) name = "<boolArrayKlass>"; else
52 52 if (_klass == Universe::charArrayKlassObj()) name = "<charArrayKlass>"; else
53 53 if (_klass == Universe::singleArrayKlassObj()) name = "<singleArrayKlass>"; else
54 54 if (_klass == Universe::doubleArrayKlassObj()) name = "<doubleArrayKlass>"; else
55 55 if (_klass == Universe::byteArrayKlassObj()) name = "<byteArrayKlass>"; else
56 56 if (_klass == Universe::shortArrayKlassObj()) name = "<shortArrayKlass>"; else
57 57 if (_klass == Universe::intArrayKlassObj()) name = "<intArrayKlass>"; else
↓ 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 }
94 97
95 98 void KlassInfoBucket::empty() {
↓ 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) :
153 173 _title(title) {
154 174 _elements = new (ResourceObj::C_HEAP) GrowableArray<KlassInfoEntry*>(estimatedCount,true);
155 175 }
156 176
157 177 KlassInfoHisto::~KlassInfoHisto() {
158 178 delete _elements;
159 179 }
160 180
161 181 void KlassInfoHisto::add(KlassInfoEntry* cie) {
162 182 elements()->append(cie);
163 183 }
164 184
165 185 void KlassInfoHisto::sort() {
166 186 elements()->sort(KlassInfoHisto::sort_helper);
167 187 }
168 188
↓ 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:
190 210 KlassInfoHisto* _cih;
191 211 public:
↓ 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;
218 244 gch->gc_prologue(false /* !full */); // get any necessary locks
219 245 ref = gch->perm_gen()->used_region().start();
220 246 break;
221 247 }
222 248 #ifndef SERIALGC
↓ 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:
258 294 klassOop _klass;
259 295 GrowableArray<oop>* _result;
260 296
261 297 public:
262 298 FindInstanceClosure(klassOop k, GrowableArray<oop>* result) : _klass(k), _result(result) {};
263 299
264 300 void do_object(oop obj) {
265 301 if (obj->is_a(_klass)) {
266 302 _result->append(obj);
267 303 }
268 304 }
269 305 };
270 306
271 307 void HeapInspection::find_instances_at_safepoint(klassOop k, GrowableArray<oop>* result) {
272 308 assert(SafepointSynchronize::is_at_safepoint(), "all threads are stopped");
273 309 assert(Heap_lock->is_locked(), "should have the Heap_lock")
274 310
275 311 // Ensure that the heap is parsable
276 312 Universe::heap()->ensure_parsability(false); // no need to retire TALBs
277 313
278 314 // Iterate over objects in the heap
279 315 FindInstanceClosure fic(k, result);
280 316 Universe::heap()->object_iterate(&fic);
281 317 }
↓ open down ↓ |
24 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX