src/share/vm/memory/heapInspection.cpp

Wed, 01 Dec 2010 15:04:06 +0100

author
stefank
date
Wed, 01 Dec 2010 15:04:06 +0100
changeset 2325
c760f78e0a53
parent 2314
f95d63e2154a
child 2497
3582bf76420e
permissions
-rw-r--r--

7003125: precompiled.hpp is included when precompiled headers are not used
Summary: Added an ifndef DONT_USE_PRECOMPILED_HEADER to precompiled.hpp. Set up DONT_USE_PRECOMPILED_HEADER when compiling with Sun Studio or when the user specifies USE_PRECOMPILED_HEADER=0. Fixed broken include dependencies.
Reviewed-by: coleenp, kvn

     1 /*
     2  * Copyright (c) 2002, 2010, 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 "oops/klassOop.hpp"
    31 #include "runtime/os.hpp"
    32 #include "utilities/globalDefinitions.hpp"
    33 #ifndef SERIALGC
    34 #include "gc_implementation/parallelScavenge/parallelScavengeHeap.hpp"
    35 #endif
    37 // HeapInspection
    39 int KlassInfoEntry::compare(KlassInfoEntry* e1, KlassInfoEntry* e2) {
    40   if(e1->_instance_words > e2->_instance_words) {
    41     return -1;
    42   } else if(e1->_instance_words < e2->_instance_words) {
    43     return 1;
    44   }
    45   return 0;
    46 }
    48 void KlassInfoEntry::print_on(outputStream* st) const {
    49   ResourceMark rm;
    50   const char* name;;
    51   if (_klass->klass_part()->name() != NULL) {
    52     name = _klass->klass_part()->external_name();
    53   } else {
    54     if (_klass == Universe::klassKlassObj())             name = "<klassKlass>";             else
    55     if (_klass == Universe::arrayKlassKlassObj())        name = "<arrayKlassKlass>";        else
    56     if (_klass == Universe::objArrayKlassKlassObj())     name = "<objArrayKlassKlass>";     else
    57     if (_klass == Universe::instanceKlassKlassObj())     name = "<instanceKlassKlass>";     else
    58     if (_klass == Universe::typeArrayKlassKlassObj())    name = "<typeArrayKlassKlass>";    else
    59     if (_klass == Universe::symbolKlassObj())            name = "<symbolKlass>";            else
    60     if (_klass == Universe::boolArrayKlassObj())         name = "<boolArrayKlass>";         else
    61     if (_klass == Universe::charArrayKlassObj())         name = "<charArrayKlass>";         else
    62     if (_klass == Universe::singleArrayKlassObj())       name = "<singleArrayKlass>";       else
    63     if (_klass == Universe::doubleArrayKlassObj())       name = "<doubleArrayKlass>";       else
    64     if (_klass == Universe::byteArrayKlassObj())         name = "<byteArrayKlass>";         else
    65     if (_klass == Universe::shortArrayKlassObj())        name = "<shortArrayKlass>";        else
    66     if (_klass == Universe::intArrayKlassObj())          name = "<intArrayKlass>";          else
    67     if (_klass == Universe::longArrayKlassObj())         name = "<longArrayKlass>";         else
    68     if (_klass == Universe::methodKlassObj())            name = "<methodKlass>";            else
    69     if (_klass == Universe::constMethodKlassObj())       name = "<constMethodKlass>";       else
    70     if (_klass == Universe::methodDataKlassObj())        name = "<methodDataKlass>";        else
    71     if (_klass == Universe::constantPoolKlassObj())      name = "<constantPoolKlass>";      else
    72     if (_klass == Universe::constantPoolCacheKlassObj()) name = "<constantPoolCacheKlass>"; else
    73     if (_klass == Universe::compiledICHolderKlassObj())  name = "<compiledICHolderKlass>";  else
    74       name = "<no name>";
    75   }
    76   // simplify the formatting (ILP32 vs LP64) - always cast the numbers to 64-bit
    77   st->print_cr(INT64_FORMAT_W(13) "  " UINT64_FORMAT_W(13) "  %s",
    78                (jlong)  _instance_count,
    79                (julong) _instance_words * HeapWordSize,
    80                name);
    81 }
    83 KlassInfoEntry* KlassInfoBucket::lookup(const klassOop k) {
    84   KlassInfoEntry* elt = _list;
    85   while (elt != NULL) {
    86     if (elt->is_equal(k)) {
    87       return elt;
    88     }
    89     elt = elt->next();
    90   }
    91   elt = new KlassInfoEntry(k, list());
    92   // We may be out of space to allocate the new entry.
    93   if (elt != NULL) {
    94     set_list(elt);
    95   }
    96   return elt;
    97 }
    99 void KlassInfoBucket::iterate(KlassInfoClosure* cic) {
   100   KlassInfoEntry* elt = _list;
   101   while (elt != NULL) {
   102     cic->do_cinfo(elt);
   103     elt = elt->next();
   104   }
   105 }
   107 void KlassInfoBucket::empty() {
   108   KlassInfoEntry* elt = _list;
   109   _list = NULL;
   110   while (elt != NULL) {
   111     KlassInfoEntry* next = elt->next();
   112     delete elt;
   113     elt = next;
   114   }
   115 }
   117 KlassInfoTable::KlassInfoTable(int size, HeapWord* ref) {
   118   _size = 0;
   119   _ref = ref;
   120   _buckets = NEW_C_HEAP_ARRAY(KlassInfoBucket, size);
   121   if (_buckets != NULL) {
   122     _size = size;
   123     for (int index = 0; index < _size; index++) {
   124       _buckets[index].initialize();
   125     }
   126   }
   127 }
   129 KlassInfoTable::~KlassInfoTable() {
   130   if (_buckets != NULL) {
   131     for (int index = 0; index < _size; index++) {
   132       _buckets[index].empty();
   133     }
   134     FREE_C_HEAP_ARRAY(KlassInfoBucket, _buckets);
   135     _size = 0;
   136   }
   137 }
   139 uint KlassInfoTable::hash(klassOop p) {
   140   assert(Universe::heap()->is_in_permanent((HeapWord*)p), "all klasses in permgen");
   141   return (uint)(((uintptr_t)p - (uintptr_t)_ref) >> 2);
   142 }
   144 KlassInfoEntry* KlassInfoTable::lookup(const klassOop k) {
   145   uint         idx = hash(k) % _size;
   146   assert(_buckets != NULL, "Allocation failure should have been caught");
   147   KlassInfoEntry*  e   = _buckets[idx].lookup(k);
   148   // Lookup may fail if this is a new klass for which we
   149   // could not allocate space for an new entry.
   150   assert(e == NULL || k == e->klass(), "must be equal");
   151   return e;
   152 }
   154 // Return false if the entry could not be recorded on account
   155 // of running out of space required to create a new entry.
   156 bool KlassInfoTable::record_instance(const oop obj) {
   157   klassOop      k = obj->klass();
   158   KlassInfoEntry* elt = lookup(k);
   159   // elt may be NULL if it's a new klass for which we
   160   // could not allocate space for a new entry in the hashtable.
   161   if (elt != NULL) {
   162     elt->set_count(elt->count() + 1);
   163     elt->set_words(elt->words() + obj->size());
   164     return true;
   165   } else {
   166     return false;
   167   }
   168 }
   170 void KlassInfoTable::iterate(KlassInfoClosure* cic) {
   171   assert(_size == 0 || _buckets != NULL, "Allocation failure should have been caught");
   172   for (int index = 0; index < _size; index++) {
   173     _buckets[index].iterate(cic);
   174   }
   175 }
   177 int KlassInfoHisto::sort_helper(KlassInfoEntry** e1, KlassInfoEntry** e2) {
   178   return (*e1)->compare(*e1,*e2);
   179 }
   181 KlassInfoHisto::KlassInfoHisto(const char* title, int estimatedCount) :
   182   _title(title) {
   183   _elements = new (ResourceObj::C_HEAP) GrowableArray<KlassInfoEntry*>(estimatedCount,true);
   184 }
   186 KlassInfoHisto::~KlassInfoHisto() {
   187   delete _elements;
   188 }
   190 void KlassInfoHisto::add(KlassInfoEntry* cie) {
   191   elements()->append(cie);
   192 }
   194 void KlassInfoHisto::sort() {
   195   elements()->sort(KlassInfoHisto::sort_helper);
   196 }
   198 void KlassInfoHisto::print_elements(outputStream* st) const {
   199   // simplify the formatting (ILP32 vs LP64) - store the sum in 64-bit
   200   jlong total = 0;
   201   julong totalw = 0;
   202   for(int i=0; i < elements()->length(); i++) {
   203     st->print("%4d: ", i+1);
   204     elements()->at(i)->print_on(st);
   205     total += elements()->at(i)->count();
   206     totalw += elements()->at(i)->words();
   207   }
   208   st->print_cr("Total " INT64_FORMAT_W(13) "  " UINT64_FORMAT_W(13),
   209                total, totalw * HeapWordSize);
   210 }
   212 void KlassInfoHisto::print_on(outputStream* st) const {
   213   st->print_cr("%s",title());
   214   print_elements(st);
   215 }
   217 class HistoClosure : public KlassInfoClosure {
   218  private:
   219   KlassInfoHisto* _cih;
   220  public:
   221   HistoClosure(KlassInfoHisto* cih) : _cih(cih) {}
   223   void do_cinfo(KlassInfoEntry* cie) {
   224     _cih->add(cie);
   225   }
   226 };
   228 class RecordInstanceClosure : public ObjectClosure {
   229  private:
   230   KlassInfoTable* _cit;
   231   size_t _missed_count;
   232  public:
   233   RecordInstanceClosure(KlassInfoTable* cit) :
   234     _cit(cit), _missed_count(0) {}
   236   void do_object(oop obj) {
   237     if (!_cit->record_instance(obj)) {
   238       _missed_count++;
   239     }
   240   }
   242   size_t missed_count() { return _missed_count; }
   243 };
   245 void HeapInspection::heap_inspection(outputStream* st, bool need_prologue) {
   246   ResourceMark rm;
   247   HeapWord* ref;
   249   CollectedHeap* heap = Universe::heap();
   250   bool is_shared_heap = false;
   251   switch (heap->kind()) {
   252     case CollectedHeap::G1CollectedHeap:
   253     case CollectedHeap::GenCollectedHeap: {
   254       is_shared_heap = true;
   255       SharedHeap* sh = (SharedHeap*)heap;
   256       if (need_prologue) {
   257         sh->gc_prologue(false /* !full */); // get any necessary locks, etc.
   258       }
   259       ref = sh->perm_gen()->used_region().start();
   260       break;
   261     }
   262 #ifndef SERIALGC
   263     case CollectedHeap::ParallelScavengeHeap: {
   264       ParallelScavengeHeap* psh = (ParallelScavengeHeap*)heap;
   265       ref = psh->perm_gen()->object_space()->used_region().start();
   266       break;
   267     }
   268 #endif // SERIALGC
   269     default:
   270       ShouldNotReachHere(); // Unexpected heap kind for this op
   271   }
   272   // Collect klass instance info
   273   KlassInfoTable cit(KlassInfoTable::cit_size, ref);
   274   if (!cit.allocation_failed()) {
   275     // Iterate over objects in the heap
   276     RecordInstanceClosure ric(&cit);
   277     // If this operation encounters a bad object when using CMS,
   278     // consider using safe_object_iterate() which avoids perm gen
   279     // objects that may contain bad references.
   280     Universe::heap()->object_iterate(&ric);
   282     // Report if certain classes are not counted because of
   283     // running out of C-heap for the histogram.
   284     size_t missed_count = ric.missed_count();
   285     if (missed_count != 0) {
   286       st->print_cr("WARNING: Ran out of C-heap; undercounted " SIZE_FORMAT
   287                    " total instances in data below",
   288                    missed_count);
   289     }
   290     // Sort and print klass instance info
   291     KlassInfoHisto histo("\n"
   292                      " num     #instances         #bytes  class name\n"
   293                      "----------------------------------------------",
   294                      KlassInfoHisto::histo_initial_size);
   295     HistoClosure hc(&histo);
   296     cit.iterate(&hc);
   297     histo.sort();
   298     histo.print_on(st);
   299   } else {
   300     st->print_cr("WARNING: Ran out of C-heap; histogram not generated");
   301   }
   302   st->flush();
   304   if (need_prologue && is_shared_heap) {
   305     SharedHeap* sh = (SharedHeap*)heap;
   306     sh->gc_epilogue(false /* !full */); // release all acquired locks, etc.
   307   }
   308 }
   310 class FindInstanceClosure : public ObjectClosure {
   311  private:
   312   klassOop _klass;
   313   GrowableArray<oop>* _result;
   315  public:
   316   FindInstanceClosure(klassOop k, GrowableArray<oop>* result) : _klass(k), _result(result) {};
   318   void do_object(oop obj) {
   319     if (obj->is_a(_klass)) {
   320       _result->append(obj);
   321     }
   322   }
   323 };
   325 void HeapInspection::find_instances_at_safepoint(klassOop k, GrowableArray<oop>* result) {
   326   assert(SafepointSynchronize::is_at_safepoint(), "all threads are stopped");
   327   assert(Heap_lock->is_locked(), "should have the Heap_lock");
   329   // Ensure that the heap is parsable
   330   Universe::heap()->ensure_parsability(false);  // no need to retire TALBs
   332   // Iterate over objects in the heap
   333   FindInstanceClosure fic(k, result);
   334   // If this operation encounters a bad object when using CMS,
   335   // consider using safe_object_iterate() which avoids perm gen
   336   // objects that may contain bad references.
   337   Universe::heap()->object_iterate(&fic);
   338 }

mercurial