src/share/vm/memory/heapInspection.cpp

Thu, 17 Jan 2013 19:04:48 -0800

author
jmasa
date
Thu, 17 Jan 2013 19:04:48 -0800
changeset 4457
59a58e20dc60
parent 4037
da91efe96a93
child 4497
16fb9f942703
child 4542
db9981fd3124
permissions
-rw-r--r--

8006537: Assert when dumping archive with default methods
Reviewed-by: coleenp

     1 /*
     2  * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     8  *
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    12  * version 2 for more details (a copy is included in the LICENSE file that
    13  * accompanied this code).
    14  *
    15  * You should have received a copy of the GNU General Public License version
    16  * 2 along with this work; if not, write to the Free Software Foundation,
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    18  *
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    20  * or visit www.oracle.com if you need additional information or have any
    21  * questions.
    22  *
    23  */
    25 #include "precompiled.hpp"
    26 #include "gc_interface/collectedHeap.hpp"
    27 #include "memory/genCollectedHeap.hpp"
    28 #include "memory/heapInspection.hpp"
    29 #include "memory/resourceArea.hpp"
    30 #include "runtime/os.hpp"
    31 #include "utilities/globalDefinitions.hpp"
    32 #ifndef SERIALGC
    33 #include "gc_implementation/parallelScavenge/parallelScavengeHeap.hpp"
    34 #endif
    36 // HeapInspection
    38 int KlassInfoEntry::compare(KlassInfoEntry* e1, KlassInfoEntry* e2) {
    39   if(e1->_instance_words > e2->_instance_words) {
    40     return -1;
    41   } else if(e1->_instance_words < e2->_instance_words) {
    42     return 1;
    43   }
    44   return 0;
    45 }
    47 void KlassInfoEntry::print_on(outputStream* st) const {
    48   ResourceMark rm;
    49   const char* name;;
    50   if (_klass->name() != NULL) {
    51     name = _klass->external_name();
    52   } else {
    53     if (_klass == Universe::boolArrayKlassObj())         name = "<boolArrayKlass>";         else
    54     if (_klass == Universe::charArrayKlassObj())         name = "<charArrayKlass>";         else
    55     if (_klass == Universe::singleArrayKlassObj())       name = "<singleArrayKlass>";       else
    56     if (_klass == Universe::doubleArrayKlassObj())       name = "<doubleArrayKlass>";       else
    57     if (_klass == Universe::byteArrayKlassObj())         name = "<byteArrayKlass>";         else
    58     if (_klass == Universe::shortArrayKlassObj())        name = "<shortArrayKlass>";        else
    59     if (_klass == Universe::intArrayKlassObj())          name = "<intArrayKlass>";          else
    60     if (_klass == Universe::longArrayKlassObj())         name = "<longArrayKlass>";         else
    61       name = "<no name>";
    62   }
    63   // simplify the formatting (ILP32 vs LP64) - always cast the numbers to 64-bit
    64   st->print_cr(INT64_FORMAT_W(13) "  " UINT64_FORMAT_W(13) "  %s",
    65                (jlong)  _instance_count,
    66                (julong) _instance_words * HeapWordSize,
    67                name);
    68 }
    70 KlassInfoEntry* KlassInfoBucket::lookup(Klass* const k) {
    71   KlassInfoEntry* elt = _list;
    72   while (elt != NULL) {
    73     if (elt->is_equal(k)) {
    74       return elt;
    75     }
    76     elt = elt->next();
    77   }
    78   elt = new KlassInfoEntry(k, list());
    79   // We may be out of space to allocate the new entry.
    80   if (elt != NULL) {
    81     set_list(elt);
    82   }
    83   return elt;
    84 }
    86 void KlassInfoBucket::iterate(KlassInfoClosure* cic) {
    87   KlassInfoEntry* elt = _list;
    88   while (elt != NULL) {
    89     cic->do_cinfo(elt);
    90     elt = elt->next();
    91   }
    92 }
    94 void KlassInfoBucket::empty() {
    95   KlassInfoEntry* elt = _list;
    96   _list = NULL;
    97   while (elt != NULL) {
    98     KlassInfoEntry* next = elt->next();
    99     delete elt;
   100     elt = next;
   101   }
   102 }
   104 KlassInfoTable::KlassInfoTable(int size, HeapWord* ref) {
   105   _size = 0;
   106   _ref = ref;
   107   _buckets = NEW_C_HEAP_ARRAY(KlassInfoBucket, size, mtInternal);
   108   if (_buckets != NULL) {
   109     _size = size;
   110     for (int index = 0; index < _size; index++) {
   111       _buckets[index].initialize();
   112     }
   113   }
   114 }
   116 KlassInfoTable::~KlassInfoTable() {
   117   if (_buckets != NULL) {
   118     for (int index = 0; index < _size; index++) {
   119       _buckets[index].empty();
   120     }
   121     FREE_C_HEAP_ARRAY(KlassInfoBucket, _buckets, mtInternal);
   122     _size = 0;
   123   }
   124 }
   126 uint KlassInfoTable::hash(Klass* p) {
   127   assert(p->is_metadata(), "all klasses are metadata");
   128   return (uint)(((uintptr_t)p - (uintptr_t)_ref) >> 2);
   129 }
   131 KlassInfoEntry* KlassInfoTable::lookup(Klass* const k) {
   132   uint         idx = hash(k) % _size;
   133   assert(_buckets != NULL, "Allocation failure should have been caught");
   134   KlassInfoEntry*  e   = _buckets[idx].lookup(k);
   135   // Lookup may fail if this is a new klass for which we
   136   // could not allocate space for an new entry.
   137   assert(e == NULL || k == e->klass(), "must be equal");
   138   return e;
   139 }
   141 // Return false if the entry could not be recorded on account
   142 // of running out of space required to create a new entry.
   143 bool KlassInfoTable::record_instance(const oop obj) {
   144   Klass*        k = obj->klass();
   145   KlassInfoEntry* elt = lookup(k);
   146   // elt may be NULL if it's a new klass for which we
   147   // could not allocate space for a new entry in the hashtable.
   148   if (elt != NULL) {
   149     elt->set_count(elt->count() + 1);
   150     elt->set_words(elt->words() + obj->size());
   151     return true;
   152   } else {
   153     return false;
   154   }
   155 }
   157 void KlassInfoTable::iterate(KlassInfoClosure* cic) {
   158   assert(_size == 0 || _buckets != NULL, "Allocation failure should have been caught");
   159   for (int index = 0; index < _size; index++) {
   160     _buckets[index].iterate(cic);
   161   }
   162 }
   164 int KlassInfoHisto::sort_helper(KlassInfoEntry** e1, KlassInfoEntry** e2) {
   165   return (*e1)->compare(*e1,*e2);
   166 }
   168 KlassInfoHisto::KlassInfoHisto(const char* title, int estimatedCount) :
   169   _title(title) {
   170   _elements = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<KlassInfoEntry*>(estimatedCount,true);
   171 }
   173 KlassInfoHisto::~KlassInfoHisto() {
   174   delete _elements;
   175 }
   177 void KlassInfoHisto::add(KlassInfoEntry* cie) {
   178   elements()->append(cie);
   179 }
   181 void KlassInfoHisto::sort() {
   182   elements()->sort(KlassInfoHisto::sort_helper);
   183 }
   185 void KlassInfoHisto::print_elements(outputStream* st) const {
   186   // simplify the formatting (ILP32 vs LP64) - store the sum in 64-bit
   187   jlong total = 0;
   188   julong totalw = 0;
   189   for(int i=0; i < elements()->length(); i++) {
   190     st->print("%4d: ", i+1);
   191     elements()->at(i)->print_on(st);
   192     total += elements()->at(i)->count();
   193     totalw += elements()->at(i)->words();
   194   }
   195   st->print_cr("Total " INT64_FORMAT_W(13) "  " UINT64_FORMAT_W(13),
   196                total, totalw * HeapWordSize);
   197 }
   199 void KlassInfoHisto::print_on(outputStream* st) const {
   200   st->print_cr("%s",title());
   201   print_elements(st);
   202 }
   204 class HistoClosure : public KlassInfoClosure {
   205  private:
   206   KlassInfoHisto* _cih;
   207  public:
   208   HistoClosure(KlassInfoHisto* cih) : _cih(cih) {}
   210   void do_cinfo(KlassInfoEntry* cie) {
   211     _cih->add(cie);
   212   }
   213 };
   215 class RecordInstanceClosure : public ObjectClosure {
   216  private:
   217   KlassInfoTable* _cit;
   218   size_t _missed_count;
   219  public:
   220   RecordInstanceClosure(KlassInfoTable* cit) :
   221     _cit(cit), _missed_count(0) {}
   223   void do_object(oop obj) {
   224     if (!_cit->record_instance(obj)) {
   225       _missed_count++;
   226     }
   227   }
   229   size_t missed_count() { return _missed_count; }
   230 };
   232 void HeapInspection::heap_inspection(outputStream* st, bool need_prologue) {
   233   ResourceMark rm;
   234   // Get some random number for ref (the hash key)
   235   HeapWord* ref = (HeapWord*) Universe::boolArrayKlassObj();
   236   CollectedHeap* heap = Universe::heap();
   237   bool is_shared_heap = false;
   239   // Collect klass instance info
   240   KlassInfoTable cit(KlassInfoTable::cit_size, ref);
   241   if (!cit.allocation_failed()) {
   242     // Iterate over objects in the heap
   243     RecordInstanceClosure ric(&cit);
   244     Universe::heap()->object_iterate(&ric);
   246     // Report if certain classes are not counted because of
   247     // running out of C-heap for the histogram.
   248     size_t missed_count = ric.missed_count();
   249     if (missed_count != 0) {
   250       st->print_cr("WARNING: Ran out of C-heap; undercounted " SIZE_FORMAT
   251                    " total instances in data below",
   252                    missed_count);
   253     }
   254     // Sort and print klass instance info
   255     KlassInfoHisto histo("\n"
   256                      " num     #instances         #bytes  class name\n"
   257                      "----------------------------------------------",
   258                      KlassInfoHisto::histo_initial_size);
   259     HistoClosure hc(&histo);
   260     cit.iterate(&hc);
   261     histo.sort();
   262     histo.print_on(st);
   263   } else {
   264     st->print_cr("WARNING: Ran out of C-heap; histogram not generated");
   265   }
   266   st->flush();
   268   if (need_prologue && is_shared_heap) {
   269     SharedHeap* sh = (SharedHeap*)heap;
   270     sh->gc_epilogue(false /* !full */); // release all acquired locks, etc.
   271   }
   272 }
   274 class FindInstanceClosure : public ObjectClosure {
   275  private:
   276   Klass* _klass;
   277   GrowableArray<oop>* _result;
   279  public:
   280   FindInstanceClosure(Klass* k, GrowableArray<oop>* result) : _klass(k), _result(result) {};
   282   void do_object(oop obj) {
   283     if (obj->is_a(_klass)) {
   284       _result->append(obj);
   285     }
   286   }
   287 };
   289 void HeapInspection::find_instances_at_safepoint(Klass* k, GrowableArray<oop>* result) {
   290   assert(SafepointSynchronize::is_at_safepoint(), "all threads are stopped");
   291   assert(Heap_lock->is_locked(), "should have the Heap_lock");
   293   // Ensure that the heap is parsable
   294   Universe::heap()->ensure_parsability(false);  // no need to retire TALBs
   296   // Iterate over objects in the heap
   297   FindInstanceClosure fic(k, result);
   298   // If this operation encounters a bad object when using CMS,
   299   // consider using safe_object_iterate() which avoids metadata
   300   // objects that may contain bad references.
   301   Universe::heap()->object_iterate(&fic);
   302 }

mercurial