/* * Copyright (c) 2017, 2021, 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. *
*/
// The metadata hierarchy is separate from the oop hierarchy class MetaspaceObj; // no C++ vtable //class Array; // no C++ vtable class Annotations; // no C++ vtable class ConstantPoolCache; // no C++ vtable class ConstMethod; // no C++ vtable class MethodCounters; // no C++ vtable class Symbol; // no C++ vtable class Metadata; // has C++ vtable (so do all subclasses) class ConstantPool; class MethodData; class Method; class Klass; class InstanceKlass; class InstanceMirrorKlass; class InstanceClassLoaderKlass; class InstanceRefKlass; class ArrayKlass; class ObjArrayKlass; class TypeArrayKlass;
// class MetaspaceClosure -- // // This class is used for iterating the objects in the HotSpot Metaspaces. It // provides an API to walk all the reachable objects starting from a set of // root references (such as all Klass'es in the SystemDictionary). // // Currently it is used for compacting the CDS archive by eliminate temporary // objects allocated during archive creation time. See ArchiveBuilder for an example. // // To support MetaspaceClosure, each subclass of MetaspaceObj must provide // a method of the type void metaspace_pointers_do(MetaspaceClosure*). This method // should call MetaspaceClosure::push() on every pointer fields of this // class that points to a MetaspaceObj. See Annotations::metaspace_pointers_do() // for an example. class MetaspaceClosure { public: enum Writability {
_writable,
_not_writable,
_default
};
enum SpecialRef {
_method_entry_ref
};
// class MetaspaceClosure::Ref -- // // MetaspaceClosure can be viewed as a very simple type of copying garbage // collector. For it to function properly, it requires each subclass of // MetaspaceObj to provide two methods: // // size_t size(); -- to determine how much data to copy // void metaspace_pointers_do(MetaspaceClosure*); -- to locate all the embedded pointers // // Calling these methods would be trivial if these two were virtual methods. // However, to save space, MetaspaceObj has NO vtable. The vtable is introduced // only in the Metadata class. // // To work around the lack of a vtable, we use the Ref class with templates // (see MSORef, OtherArrayRef, MSOArrayRef, and MSOPointerArrayRef) // so that we can statically discover the type of a object. The use of Ref // depends on the fact that: // // [1] We don't use polymorphic pointers for MetaspaceObj's that are not subclasses // of Metadata. I.e., we don't do this: // class Klass { // MetaspaceObj *_obj; // Array<int>* foo() { return (Array<int>*)_obj; } // Symbol* bar() { return (Symbol*) _obj; } // // [2] All Array<T> dimensions are statically declared. class Ref : public CHeapObj<mtMetaspace> {
Writability _writability; bool _keep_after_pushing;
Ref* _next; void* _user_data;
NONCOPYABLE(Ref);
// OtherArrayRef -- iterate an instance of Array<T>, where T is NOT a subtype of MetaspaceObj. // T can be a primitive type, such as int, or a structure. However, we do not scan // the fields inside T, so you should not embed any pointers inside T. template <class T> class OtherArrayRef : public ArrayRef<T> { public:
OtherArrayRef(Array<T>** mpp, Writability w) : ArrayRef<T>(mpp, w) {}
// MSOArrayRef -- iterate an instance of Array<T>, where T is a subtype of MetaspaceObj. // We recursively call T::metaspace_pointers_do() for each element in this array. template <class T> class MSOArrayRef : public ArrayRef<T> { public:
MSOArrayRef(Array<T>** mpp, Writability w) : ArrayRef<T>(mpp, w) {}
// MSOPointerArrayRef -- iterate an instance of Array<T*>, where T is a subtype of MetaspaceObj. // We recursively call MetaspaceClosure::push() for each pointer in this array. template <class T> class MSOPointerArrayRef : public ArrayRef<T*> { public:
MSOPointerArrayRef(Array<T*>** mpp, Writability w) : ArrayRef<T*>(mpp, w) {}
// Normally, chains of references like a->b->c->d are iterated recursively. However, // if recursion is too deep, we save the Refs in _pending_refs, and push them later in // MetaspaceClosure::finish(). This avoids overflowing the C stack. staticconstint MAX_NEST_LEVEL = 5;
Ref* _pending_refs; int _nest_level;
Ref* _enclosing_ref;
// enclosing_ref() is used to compute the offset of a field in a C++ class. For example // class Foo { intx scala; Bar* ptr; } // Foo *f = 0x100; // when the f->ptr field is iterated with do_ref() on 64-bit platforms, we will have // do_ref(Ref* r) { // r->addr() == 0x108; // == &f->ptr; // enclosing_ref()->obj() == 0x100; // == foo // So we know that we are iterating upon a field at offset 8 of the object at 0x100. // // Note that if we have stack overflow, do_pending_ref(r) will be called first and // do_ref(r) will be called later, for the same r. In this case, enclosing_ref() is valid only // when do_pending_ref(r) is called, and will return NULL when do_ref(r) is called.
Ref* enclosing_ref() const { return _enclosing_ref;
}
// This is called when a reference is placed in _pending_refs. Override this // function if you're using enclosing_ref(). See notes above. virtualvoid do_pending_ref(Ref* ref) {}
// returns true if we want to keep iterating the pointers embedded inside <ref> virtualbool do_ref(Ref* ref, bool read_only) = 0;
public: // When MetaspaceClosure::push(...) is called, pick the correct Ref subtype to handle it: // // MetaspaceClosure* it = ...; // Klass* o = ...; it->push(&o); => MSORef // Array<int>* a1 = ...; it->push(&a1); => OtherArrayRef // Array<Annotation>* a2 = ...; it->push(&a2); => MSOArrayRef // Array<Klass*>* a3 = ...; it->push(&a3); => MSOPointerArrayRef // Array<Array<Klass*>*>* a4 = ...; it->push(&a4); => MSOPointerArrayRef // Array<Annotation*>* a5 = ...; it->push(&a5); => MSOPointerArrayRef // // Note that the following will fail to compile (to prevent you from adding new fields // into the MetaspaceObj subtypes that cannot be properly copied by CDS): // // Hashtable* h = ...; it->push(&h); => Hashtable is not a subclass of MetaspaceObj // Array<Hashtable*>* a6 = ...; it->push(&a6); => Hashtable is not a subclass of MetaspaceObj // Array<int*>* a7 = ...; it->push(&a7); => int is not a subclass of MetaspaceObj
template <typename T> void push(T** mpp, Writability w = _default) {
static_assert(std::is_base_of<MetaspaceObj, T>::value, "Do not push pointers of arbitrary types");
push_with_ref<MSORef<T>>(mpp, w);
}
template <typename T> void push(Array<T*>** mpp, Writability w = _default) {
static_assert(std::is_base_of<MetaspaceObj, T>::value, "Do not push Arrays of arbitrary pointer types");
push_with_ref<MSOPointerArrayRef<T>>(mpp, w);
}
#if 0 // Enable this block if you're changing the push(...) methods, to test for types that should be // disallowed. Each of the following "push" calls should result in a compile-time error. void test_disallowed_types(MetaspaceClosure* it) {
Hashtable<bool, mtInternal>* h = NULL;
it->push(&h);
// This is for tagging special pointers that are not a reference to MetaspaceObj. It's currently // used to mark the method entry points in Method/ConstMethod. virtualvoid push_special(SpecialRef type, Ref* obj, intptr_t* p) {
assert(type == _method_entry_ref, "only special type allowed for now");
}
};
// This is a special MetaspaceClosure that visits each unique MetaspaceObj once. class UniqueMetaspaceClosure : public MetaspaceClosure { staticconstint INITIAL_TABLE_SIZE = 15889; staticconstint MAX_TABLE_SIZE = 1000000;
// Do not override. Returns true if we are discovering ref->obj() for the first time. virtualbool do_ref(Ref* ref, bool read_only);
public: // Gets called the first time we discover an object. virtualbool do_unique_ref(Ref* ref, bool read_only) = 0;
UniqueMetaspaceClosure() : _has_been_visited(INITIAL_TABLE_SIZE, MAX_TABLE_SIZE) {}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.