/* * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. * */ #ifndef SHARE_VM_MEMORY_HEAPINSPECTION_HPP #define SHARE_VM_MEMORY_HEAPINSPECTION_HPP #include "memory/allocation.inline.hpp" #include "oops/oop.inline.hpp" // HeapInspection // KlassInfoTable is a bucket hash table that // maps klassOops to extra information: // instance count and instance word size. // // A KlassInfoBucket is the head of a link list // of KlassInfoEntry's // // KlassInfoHisto is a growable array of pointers // to KlassInfoEntry's and is used to sort // the entries. class KlassInfoEntry: public CHeapObj { private: KlassInfoEntry* _next; klassOop _klass; long _instance_count; size_t _instance_words; public: KlassInfoEntry(klassOop k, KlassInfoEntry* next) : _klass(k), _instance_count(0), _instance_words(0), _next(next) {} KlassInfoEntry* next() { return _next; } bool is_equal(klassOop k) { return k == _klass; } klassOop klass() { return _klass; } long count() { return _instance_count; } void set_count(long ct) { _instance_count = ct; } size_t words() { return _instance_words; } void set_words(size_t wds) { _instance_words = wds; } int compare(KlassInfoEntry* e1, KlassInfoEntry* e2); void print_on(outputStream* st) const; }; class KlassInfoClosure: public StackObj { public: // Called for each KlassInfoEntry. virtual void do_cinfo(KlassInfoEntry* cie) = 0; }; class KlassInfoBucket: public CHeapObj { private: KlassInfoEntry* _list; KlassInfoEntry* list() { return _list; } void set_list(KlassInfoEntry* l) { _list = l; } public: KlassInfoEntry* lookup(const klassOop k); void initialize() { _list = NULL; } void empty(); void iterate(KlassInfoClosure* cic); }; class KlassInfoTable: public StackObj { private: int _size; // An aligned reference address (typically the least // address in the perm gen) used for hashing klass // objects. HeapWord* _ref; KlassInfoBucket* _buckets; uint hash(klassOop p); KlassInfoEntry* lookup(const klassOop k); public: // Table size enum { cit_size = 20011 }; KlassInfoTable(int size, HeapWord* ref); ~KlassInfoTable(); bool record_instance(const oop obj); void iterate(KlassInfoClosure* cic); bool allocation_failed() { return _buckets == NULL; } }; class KlassInfoHisto : public StackObj { private: GrowableArray* _elements; GrowableArray* elements() const { return _elements; } const char* _title; const char* title() const { return _title; } static int sort_helper(KlassInfoEntry** e1, KlassInfoEntry** e2); void print_elements(outputStream* st) const; public: enum { histo_initial_size = 1000 }; KlassInfoHisto(const char* title, int estimatedCount); ~KlassInfoHisto(); void add(KlassInfoEntry* cie); void print_on(outputStream* st) const; void sort(); }; class HeapInspection : public AllStatic { public: static void heap_inspection(outputStream* st, bool need_prologue); static void find_instances_at_safepoint(klassOop k, GrowableArray* result); static void instance_inspection(KlassInfoClosure* closure); static void instance_inspection(BoolObjectClosure* object_filter, KlassInfoClosure* closure); static HeapWord* create_random_seed(); private: static bool is_shared_heap(); static size_t iterate_over_heap(KlassInfoTable* cit); static size_t iterate_over_heap(BoolObjectClosure* object_filter, KlassInfoTable* cit); }; #endif // SHARE_VM_MEMORY_HEAPINSPECTION_HPP