< prev index next >

src/hotspot/share/classfile/classLoaderData.hpp

Print this page

        

*** 24,44 **** #ifndef SHARE_VM_CLASSFILE_CLASSLOADERDATA_HPP #define SHARE_VM_CLASSFILE_CLASSLOADERDATA_HPP #include "memory/allocation.hpp" - #include "memory/memRegion.hpp" - #include "memory/metaspace.hpp" - #include "memory/metaspaceCounters.hpp" #include "oops/oopHandle.hpp" ! #include "runtime/mutex.hpp" #include "trace/traceMacros.hpp" #include "utilities/growableArray.hpp" #include "utilities/macros.hpp" - #if INCLUDE_TRACE - #include "utilities/ticks.hpp" - #endif // // A class loader represents a linkset. Conceptually, a linkset identifies // the complete transitive closure of resolved links that a dynamic linker can // produce. --- 24,38 ---- #ifndef SHARE_VM_CLASSFILE_CLASSLOADERDATA_HPP #define SHARE_VM_CLASSFILE_CLASSLOADERDATA_HPP #include "memory/allocation.hpp" #include "oops/oopHandle.hpp" ! #include "runtime/handles.hpp" #include "trace/traceMacros.hpp" #include "utilities/growableArray.hpp" #include "utilities/macros.hpp" // // A class loader represents a linkset. Conceptually, a linkset identifies // the complete transitive closure of resolved links that a dynamic linker can // produce.
*** 49,74 **** // // ClassLoaderData are stored in the runtime representation of classes, // and provides iterators for root tracing and other GC operations. class ClassLoaderData; class JNIMethodBlock; ! class Metadebug; class ModuleEntry; - class PackageEntry; class ModuleEntryTable; class PackageEntryTable; - class DictionaryEntry; - class Dictionary; // GC root for walking class loader data created class ClassLoaderDataGraph : public AllStatic { friend class ClassLoaderData; - friend class ClassLoaderDataGraphMetaspaceIterator; friend class ClassLoaderDataGraphKlassIteratorAtomic; friend class ClassLoaderDataGraphKlassIteratorStatic; friend class VMStructs; private: // All CLDs (except the null CLD) can be reached by walking _head->_next->... static ClassLoaderData* _head; static ClassLoaderData* _unloading; --- 43,68 ---- // // ClassLoaderData are stored in the runtime representation of classes, // and provides iterators for root tracing and other GC operations. class ClassLoaderData; + class Dictionary; class JNIMethodBlock; ! class Metaspace; class ModuleEntry; class ModuleEntryTable; + class Mutex; + class PackageEntry; class PackageEntryTable; // GC root for walking class loader data created class ClassLoaderDataGraph : public AllStatic { friend class ClassLoaderData; friend class ClassLoaderDataGraphKlassIteratorAtomic; friend class ClassLoaderDataGraphKlassIteratorStatic; + friend class ClassLoaderDataGraphMetaspaceIterator; friend class VMStructs; private: // All CLDs (except the null CLD) can be reached by walking _head->_next->... static ClassLoaderData* _head; static ClassLoaderData* _unloading;
*** 79,89 **** // OOM has been seen in metaspace allocation. Used to prevent some // allocations until class unloading static bool _metaspace_oom; static ClassLoaderData* add(Handle class_loader, bool anonymous, TRAPS); - static void post_class_unload_events(); public: static ClassLoaderData* find_or_create(Handle class_loader, TRAPS); static void purge(); static void clear_claimed_marks(); // oops do --- 73,82 ----
*** 147,254 **** static bool has_metaspace_oom() { return _metaspace_oom; } static void set_metaspace_oom(bool value) { _metaspace_oom = value; } static void dump_on(outputStream * const out) PRODUCT_RETURN; - static void dump() { dump_on(tty); } - static void verify(); - static void print_creation(outputStream* out, Handle loader, ClassLoaderData* cld, TRAPS); - static bool unload_list_contains(const void* x); - #ifndef PRODUCT - static bool contains_loader_data(ClassLoaderData* loader_data); - #endif ! #if INCLUDE_TRACE ! private: ! static Ticks _class_unload_time; ! static void class_unload_event(Klass* const k); ! #endif }; // ClassLoaderData class class ClassLoaderData : public CHeapObj<mtClass> { friend class VMStructs; private: class Dependencies VALUE_OBJ_CLASS_SPEC { objArrayOop _list_head; - void locked_add(objArrayHandle last, - objArrayHandle new_dependency, - Thread* THREAD); - public: Dependencies() : _list_head(NULL) {} ! Dependencies(TRAPS) : _list_head(NULL) { ! init(CHECK); ! } ! void add(Handle dependency, TRAPS); void init(TRAPS); void oops_do(OopClosure* f); }; class ChunkedHandleList VALUE_OBJ_CLASS_SPEC { struct Chunk : public CHeapObj<mtClass> { static const size_t CAPACITY = 32; - oop _data[CAPACITY]; volatile juint _size; Chunk* _next; ! ! Chunk(Chunk* c) : _next(c), _size(0) { } }; - Chunk* volatile _head; - - void oops_do_chunk(OopClosure* f, Chunk* c, const juint size); - - public: ChunkedHandleList() : _head(NULL) {} ~ChunkedHandleList(); // Only one thread at a time can add, guarded by ClassLoaderData::metaspace_lock(). // However, multiple threads can execute oops_do concurrently with add. oop* add(oop o); - #ifdef ASSERT - bool contains(oop* p); - #endif void oops_do(OopClosure* f); }; ! friend class ClassLoaderDataGraph; ! friend class ClassLoaderDataGraphKlassIteratorAtomic; ! friend class ClassLoaderDataGraphKlassIteratorStatic; ! friend class ClassLoaderDataGraphMetaspaceIterator; ! friend class MetaDataFactory; ! friend class Method; ! static ClassLoaderData * _the_null_class_loader_data; oop _class_loader; // oop used to uniquely identify a class loader // class loader or a canonical class path - Dependencies _dependencies; // holds dependencies from this class loader - // data to others. Metaspace * volatile _metaspace; // Meta-space where meta-data defined by the // classes in the class loader are allocated. Mutex* _metaspace_lock; // Locks the metaspace for allocations and setup. - bool _unloading; // true if this class loader goes away - bool _is_anonymous; // if this CLD is for an anonymous class - - // Remembered sets support for the oops in the class loader data. - bool _modified_oops; // Card Table Equivalent (YC/CMS support) - bool _accumulated_modified_oops; // Mod Union Equivalent (CMS support) - - s2 _keep_alive; // if this CLD is kept alive without a keep_alive_object(). - // Used for anonymous classes and the boot class - // loader. _keep_alive does not need to be volatile or - // atomic since there is one unique CLD per anonymous class. - - volatile int _claimed; // true if claimed, for example during GC traces. - // To avoid applying oop closure more than once. - // Has to be an int because we cas it. - ChunkedHandleList _handles; // Handles to constant pool arrays, Modules, etc, which - // have the same life cycle of the corresponding ClassLoader. Klass* volatile _klasses; // The classes defined by the class loader. PackageEntryTable* volatile _packages; // The packages defined by the class loader. ModuleEntryTable* volatile _modules; // The modules defined by the class loader. ModuleEntry* _unnamed_module; // This class loader's unnamed module. --- 140,216 ---- static bool has_metaspace_oom() { return _metaspace_oom; } static void set_metaspace_oom(bool value) { _metaspace_oom = value; } static void dump_on(outputStream * const out) PRODUCT_RETURN; static bool unload_list_contains(const void* x); ! NOT_PRODUCT(static void verify();) ! NOT_PRODUCT(static bool contains_loader_data(ClassLoaderData* loader_data);) }; // ClassLoaderData class class ClassLoaderData : public CHeapObj<mtClass> { + friend class ClassLoaderDataGraph; + friend class ClassLoaderDataGraphKlassIteratorAtomic; + friend class ClassLoaderDataGraphKlassIteratorStatic; + friend class ClassLoaderDataGraphMetaspaceIterator; + friend class MetaDataFactory; + friend class Method; + friend class Universe; friend class VMStructs; private: class Dependencies VALUE_OBJ_CLASS_SPEC { + friend class ClassLoaderData; + friend class ClassLoaderDataGraph; + private: objArrayOop _list_head; Dependencies() : _list_head(NULL) {} ! Dependencies(TRAPS) : _list_head(NULL) { init(CHECK); } void init(TRAPS); + void add(Handle dependency, TRAPS); + void locked_add(objArrayHandle last, objArrayHandle new_dependency, Thread* THREAD); void oops_do(OopClosure* f); }; class ChunkedHandleList VALUE_OBJ_CLASS_SPEC { + friend class ClassLoaderData; + private: struct Chunk : public CHeapObj<mtClass> { static const size_t CAPACITY = 32; oop _data[CAPACITY]; volatile juint _size; Chunk* _next; ! Chunk(Chunk* c) : _next(c), _size(0) {} }; Chunk* volatile _head; ChunkedHandleList() : _head(NULL) {} ~ChunkedHandleList(); // Only one thread at a time can add, guarded by ClassLoaderData::metaspace_lock(). // However, multiple threads can execute oops_do concurrently with add. oop* add(oop o); void oops_do(OopClosure* f); + void oops_do_chunk(OopClosure* f, Chunk* c, const juint size); + DEBUG_ONLY(bool contains(oop* p);) }; ! static ClassLoaderData* _the_null_class_loader_data; ! Dependencies _dependencies; // holds dependencies from this class loader ! // data to others. ! ! ChunkedHandleList _handles; // Handles to constant pool arrays, Modules, etc, which ! // have the same life cycle of the corresponding ClassLoader. oop _class_loader; // oop used to uniquely identify a class loader // class loader or a canonical class path Metaspace * volatile _metaspace; // Meta-space where meta-data defined by the // classes in the class loader are allocated. Mutex* _metaspace_lock; // Locks the metaspace for allocations and setup. Klass* volatile _klasses; // The classes defined by the class loader. PackageEntryTable* volatile _packages; // The packages defined by the class loader. ModuleEntryTable* volatile _modules; // The modules defined by the class loader. ModuleEntry* _unnamed_module; // This class loader's unnamed module.
*** 264,432 **** GrowableArray<Metadata*>* _deallocate_list; // Support for walking class loader data objects ClassLoaderData* _next; /// Next loader_datas created ! // ReadOnly and ReadWrite metaspaces (static because only on the null ! // class loader for now). ! static Metaspace* _ro_metaspace; ! static Metaspace* _rw_metaspace; TRACE_DEFINE_TRACE_ID_FIELD; void set_next(ClassLoaderData* next) { _next = next; } ClassLoaderData* next() const { return _next; } ClassLoaderData(Handle h_class_loader, bool is_anonymous, Dependencies dependencies); ~ClassLoaderData(); ! // GC interface. ! void clear_claimed() { _claimed = 0; } ! bool claimed() const { return _claimed == 1; } ! bool claim(); // The CLD are not placed in the Heap, so the Card Table or // the Mod Union Table can't be used to mark when CLD have modified oops. // The CT and MUT bits saves this information for the whole class loader data. void clear_modified_oops() { _modified_oops = false; } - public: - void record_modified_oops() { _modified_oops = true; } - bool has_modified_oops() { return _modified_oops; } - - void accumulate_modified_oops() { if (has_modified_oops()) _accumulated_modified_oops = true; } - void clear_accumulated_modified_oops() { _accumulated_modified_oops = false; } - bool has_accumulated_modified_oops() { return _accumulated_modified_oops; } - private: - void unload(); - bool keep_alive() const { return _keep_alive > 0; } void classes_do(void f(Klass*)); - void loaded_classes_do(KlassClosure* klass_closure); void classes_do(void f(InstanceKlass*)); void methods_do(void f(Method*)); void modules_do(void f(ModuleEntry*)); void packages_do(void f(PackageEntry*)); - // Deallocate free list during class unloading. - void free_deallocate_list(); // for the classes that are not unloaded - void unload_deallocate_list(); // for the classes that are unloaded - - // Allocate out of this class loader data - MetaWord* allocate(size_t size); - - Dictionary* create_dictionary(); public: ! bool is_alive(BoolObjectClosure* is_alive_closure) const; ! ! // Accessors ! Metaspace* metaspace_or_null() const { return _metaspace; } ! ! static ClassLoaderData* the_null_class_loader_data() { ! return _the_null_class_loader_data; ! } ! ! Mutex* metaspace_lock() const { return _metaspace_lock; } ! ! bool is_anonymous() const { return _is_anonymous; } ! ! static void init_null_class_loader_data() { ! assert(_the_null_class_loader_data == NULL, "cannot initialize twice"); ! assert(ClassLoaderDataGraph::_head == NULL, "cannot initialize twice"); ! ! // We explicitly initialize the Dependencies object at a later phase in the initialization ! _the_null_class_loader_data = new ClassLoaderData(Handle(), false, Dependencies()); ! ClassLoaderDataGraph::_head = _the_null_class_loader_data; ! assert(_the_null_class_loader_data->is_the_null_class_loader_data(), "Must be"); ! } ! ! bool is_the_null_class_loader_data() const { ! return this == _the_null_class_loader_data; ! } ! bool is_system_class_loader_data() const; ! bool is_platform_class_loader_data() const; ! bool is_builtin_class_loader_data() const; ! ! // The Metaspace is created lazily so may be NULL. This ! // method will allocate a Metaspace if needed. ! Metaspace* metaspace_non_null(); ! oop class_loader() const { return _class_loader; } // The object the GC is using to keep this ClassLoaderData alive. oop keep_alive_object() const; // Returns true if this class loader data is for a loader going away. bool is_unloading() const { assert(!(is_the_null_class_loader_data() && _unloading), "The null class loader can never be unloaded"); return _unloading; } ! // Used to refcount an anonymous class's CLD in order to ! // indicate their aliveness without a keep_alive_object(). ! void inc_keep_alive(); ! void dec_keep_alive(); ! inline unsigned int identity_hash() const { return (unsigned int)(((intptr_t)this) >> 3); } ! void oops_do(OopClosure* f, bool must_claim, bool clear_modified_oops = false); - void classes_do(KlassClosure* klass_closure); Klass* klasses() { return _klasses; } JNIMethodBlock* jmethod_ids() const { return _jmethod_ids; } void set_jmethod_ids(JNIMethodBlock* new_block) { _jmethod_ids = new_block; } - void print() { print_on(tty); } - void print_on(outputStream* out) const; - void print_value() { print_value_on(tty); } - void print_value_on(outputStream* out) const; - void dump(outputStream * const out) PRODUCT_RETURN; - void verify(); - const char* loader_name(); - OopHandle add_handle(Handle h); void remove_handle(OopHandle h); void init_handle_locked(OopHandle& pd, Handle h); // used for concurrent access to ModuleEntry::_pd field void add_class(Klass* k, bool publicize = true); void remove_class(Klass* k); bool contains_klass(Klass* k); void record_dependency(const Klass* to, TRAPS); ! void init_dependencies(TRAPS); ! PackageEntryTable* packages() { return _packages; } ! ModuleEntry* unnamed_module() { return _unnamed_module; } ! ModuleEntryTable* modules(); ! bool modules_defined() { return (_modules != NULL); } ! // Loaded class dictionary ! Dictionary* dictionary() const { return _dictionary; } ! void add_to_deallocate_list(Metadata* m); static ClassLoaderData* class_loader_data(oop loader); static ClassLoaderData* class_loader_data_or_null(oop loader); static ClassLoaderData* anonymous_class_loader_data(oop loader, TRAPS); - static void print_loader(ClassLoaderData *loader_data, outputStream *out); - - TRACE_DEFINE_TRACE_ID_METHODS; }; // An iterator that distributes Klasses to parallel worker threads. class ClassLoaderDataGraphKlassIteratorAtomic : public StackObj { Klass* volatile _next_klass; public: ClassLoaderDataGraphKlassIteratorAtomic(); Klass* next_klass(); - private: static Klass* next_klass_in_cldg(Klass* klass); }; class ClassLoaderDataGraphMetaspaceIterator : public StackObj { ClassLoaderData* _data; public: ClassLoaderDataGraphMetaspaceIterator(); - ~ClassLoaderDataGraphMetaspaceIterator(); bool repeat() { return _data != NULL; } Metaspace* get_next() { assert(_data != NULL, "Should not be NULL in call to the iterator"); Metaspace* result = _data->metaspace_or_null(); _data = _data->next(); --- 226,376 ---- GrowableArray<Metadata*>* _deallocate_list; // Support for walking class loader data objects ClassLoaderData* _next; /// Next loader_datas created ! s2 _keep_alive; // if this CLD is kept alive without a keep_alive_object(). ! // Used for anonymous classes and the boot class ! // loader. _keep_alive does not need to be volatile or ! // atomic since there is one unique CLD per anonymous class. ! ! volatile int _claimed; // true if claimed, for example during GC traces. ! // To avoid applying oop closure more than once. ! // Has to be an int because we cas it. TRACE_DEFINE_TRACE_ID_FIELD; + bool _unloading; // true if this class loader goes away + bool _is_anonymous; // if this CLD is for an anonymous class + + // Remembered sets support for the oops in the class loader data. + bool _modified_oops; // Card Table Equivalent (YC/CMS support) + bool _accumulated_modified_oops; // Mod Union Equivalent (CMS support) + void set_next(ClassLoaderData* next) { _next = next; } ClassLoaderData* next() const { return _next; } ClassLoaderData(Handle h_class_loader, bool is_anonymous, Dependencies dependencies); ~ClassLoaderData(); ! void init_dependencies(TRAPS); ! ! // Deallocate free list during class unloading. ! void free_deallocate_list(); ! void unload_deallocate_list(); // for the classes that are unloaded ! ! void unload(); ! bool keep_alive() const { return _keep_alive > 0; } // The CLD are not placed in the Heap, so the Card Table or // the Mod Union Table can't be used to mark when CLD have modified oops. // The CT and MUT bits saves this information for the whole class loader data. void clear_modified_oops() { _modified_oops = false; } void classes_do(void f(Klass*)); void classes_do(void f(InstanceKlass*)); + void loaded_classes_do(KlassClosure* klass_closure); void methods_do(void f(Method*)); void modules_do(void f(ModuleEntry*)); void packages_do(void f(PackageEntry*)); public: + void oops_do(OopClosure* f, bool must_claim, bool clear_modified_oops = false); + void classes_do(KlassClosure* klass_closure); ! void record_modified_oops() { _modified_oops = true; } ! bool has_modified_oops() const { return _modified_oops; } ! void accumulate_modified_oops() { if (has_modified_oops()) _accumulated_modified_oops = true; } ! void clear_accumulated_modified_oops() { _accumulated_modified_oops = false; } ! bool has_accumulated_modified_oops() const { return _accumulated_modified_oops; } + bool is_alive(BoolObjectClosure* is_alive_closure) const; // The object the GC is using to keep this ClassLoaderData alive. oop keep_alive_object() const; + // Used to refcount an anonymous class's CLD in order to + // indicate their aliveness without a keep_alive_object(). + void inc_keep_alive(); + void dec_keep_alive(); // Returns true if this class loader data is for a loader going away. bool is_unloading() const { assert(!(is_the_null_class_loader_data() && _unloading), "The null class loader can never be unloaded"); return _unloading; } ! void clear_claimed() { _claimed = 0; } ! bool claimed() const { return _claimed == 1; } ! bool claim(); ! // The Metaspace is created lazily so may be NULL. This ! // method will allocate a Metaspace if needed. ! Metaspace* metaspace_non_null(); ! Mutex* metaspace_lock() const { return _metaspace_lock; } ! Metaspace* metaspace_or_null() const { return _metaspace; } ! bool is_the_null_class_loader_data() const { return this == _the_null_class_loader_data; } ! bool is_system_class_loader_data() const; ! bool is_platform_class_loader_data() const; ! bool is_builtin_class_loader_data() const; ! bool is_anonymous() const { return _is_anonymous; } ! ! oop class_loader() const { return _class_loader; } ! const char* loader_name(); ! unsigned int identity_hash() const { return (unsigned int)(((intptr_t)this) >> 3); } ! // Loaded class dictionary ! Dictionary* dictionary() { return _dictionary; } Klass* klasses() { return _klasses; } + PackageEntryTable* packages() { return _packages; } + ModuleEntry* unnamed_module() { return _unnamed_module; } + ModuleEntryTable* modules(); + bool modules_defined() { return (_modules != NULL); } JNIMethodBlock* jmethod_ids() const { return _jmethod_ids; } void set_jmethod_ids(JNIMethodBlock* new_block) { _jmethod_ids = new_block; } OopHandle add_handle(Handle h); void remove_handle(OopHandle h); void init_handle_locked(OopHandle& pd, Handle h); // used for concurrent access to ModuleEntry::_pd field void add_class(Klass* k, bool publicize = true); void remove_class(Klass* k); bool contains_klass(Klass* k); void record_dependency(const Klass* to, TRAPS); ! void add_to_deallocate_list(Metadata* m); ! TRACE_DEFINE_TRACE_ID_METHODS; ! void print() { print_on(tty); } ! void print_on(outputStream* out) const; ! void print_value() { print_value_on(tty); } ! void print_value_on(outputStream* out) const; ! void dump(outputStream * const out) PRODUCT_RETURN; ! NOT_PRODUCT(void verify();) + static void init_null_class_loader_data(); + static ClassLoaderData* the_null_class_loader_data() { return _the_null_class_loader_data; } static ClassLoaderData* class_loader_data(oop loader); static ClassLoaderData* class_loader_data_or_null(oop loader); static ClassLoaderData* anonymous_class_loader_data(oop loader, TRAPS); }; // An iterator that distributes Klasses to parallel worker threads. class ClassLoaderDataGraphKlassIteratorAtomic : public StackObj { + private: Klass* volatile _next_klass; public: ClassLoaderDataGraphKlassIteratorAtomic(); Klass* next_klass(); static Klass* next_klass_in_cldg(Klass* klass); }; class ClassLoaderDataGraphMetaspaceIterator : public StackObj { + private: ClassLoaderData* _data; public: ClassLoaderDataGraphMetaspaceIterator(); bool repeat() { return _data != NULL; } Metaspace* get_next() { assert(_data != NULL, "Should not be NULL in call to the iterator"); Metaspace* result = _data->metaspace_or_null(); _data = _data->next();
*** 435,440 **** --- 379,385 ---- // there is no guarantee that there will be a non-null result // down the list so the caller is going to have to check. return result; } }; + #endif // SHARE_VM_CLASSFILE_CLASSLOADERDATA_HPP
< prev index next >