src/share/vm/memory/heapInspection.cpp

Fri, 15 Apr 2011 09:36:28 -0400

author
coleenp
date
Fri, 15 Apr 2011 09:36:28 -0400
changeset 2777
8ce625481709
parent 2708
1d1603768966
child 3900
d2a62e0f25eb
permissions
-rw-r--r--

7032407: Crash in LinkResolver::runtime_resolve_virtual_method()
Summary: Make CDS reorder vtables so that dump time vtables match run time order, so when redefine classes reinitializes them, they aren't in the wrong order.
Reviewed-by: dcubed, acorn

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

mercurial