aoqi@0: /* aoqi@0: * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. aoqi@0: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. aoqi@0: * aoqi@0: * This code is free software; you can redistribute it and/or modify it aoqi@0: * under the terms of the GNU General Public License version 2 only, as aoqi@0: * published by the Free Software Foundation. aoqi@0: * aoqi@0: * This code is distributed in the hope that it will be useful, but WITHOUT aoqi@0: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or aoqi@0: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License aoqi@0: * version 2 for more details (a copy is included in the LICENSE file that aoqi@0: * accompanied this code). aoqi@0: * aoqi@0: * You should have received a copy of the GNU General Public License version aoqi@0: * 2 along with this work; if not, write to the Free Software Foundation, aoqi@0: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. aoqi@0: * aoqi@0: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA aoqi@0: * or visit www.oracle.com if you need additional information or have any aoqi@0: * questions. aoqi@0: * aoqi@0: */ aoqi@0: aoqi@0: #ifndef SHARE_VM_CLASSFILE_CLASSLOADERDATA_HPP aoqi@0: #define SHARE_VM_CLASSFILE_CLASSLOADERDATA_HPP aoqi@0: aoqi@0: #include "memory/allocation.hpp" aoqi@0: #include "memory/memRegion.hpp" aoqi@0: #include "memory/metaspace.hpp" aoqi@0: #include "memory/metaspaceCounters.hpp" aoqi@0: #include "runtime/mutex.hpp" aoqi@0: #include "utilities/growableArray.hpp" mgronlun@7367: #include "utilities/macros.hpp" aoqi@0: #if INCLUDE_TRACE mgronlun@7367: #include "utilities/ticks.hpp" aoqi@0: #endif aoqi@0: aoqi@0: // aoqi@0: // A class loader represents a linkset. Conceptually, a linkset identifies aoqi@0: // the complete transitive closure of resolved links that a dynamic linker can aoqi@0: // produce. aoqi@0: // aoqi@0: // A ClassLoaderData also encapsulates the allocation space, called a metaspace, aoqi@0: // used by the dynamic linker to allocate the runtime representation of all aoqi@0: // the types it defines. aoqi@0: // aoqi@0: // ClassLoaderData are stored in the runtime representation of classes and the aoqi@0: // system dictionary, are roots of garbage collection, and provides iterators aoqi@0: // for root tracing and other GC operations. aoqi@0: aoqi@0: class ClassLoaderData; aoqi@0: class JNIMethodBlock; aoqi@0: class JNIHandleBlock; aoqi@0: class Metadebug; aoqi@0: aoqi@0: // GC root for walking class loader data created aoqi@0: aoqi@0: class ClassLoaderDataGraph : public AllStatic { aoqi@0: friend class ClassLoaderData; aoqi@0: friend class ClassLoaderDataGraphMetaspaceIterator; stefank@6992: friend class ClassLoaderDataGraphKlassIteratorAtomic; aoqi@0: friend class VMStructs; aoqi@0: private: aoqi@0: // All CLDs (except the null CLD) can be reached by walking _head->_next->... aoqi@0: static ClassLoaderData* _head; aoqi@0: static ClassLoaderData* _unloading; aoqi@0: // CMS support. aoqi@0: static ClassLoaderData* _saved_head; aoqi@0: static ClassLoaderData* _saved_unloading; aoqi@0: static bool _should_purge; aoqi@0: aoqi@0: static ClassLoaderData* add(Handle class_loader, bool anonymous, TRAPS); aoqi@0: static void post_class_unload_events(void); stefank@7333: static void clean_metaspaces(); aoqi@0: public: aoqi@0: static ClassLoaderData* find_or_create(Handle class_loader, TRAPS); aoqi@0: static void purge(); aoqi@0: static void clear_claimed_marks(); stefank@6992: // oops do aoqi@0: static void oops_do(OopClosure* f, KlassClosure* klass_closure, bool must_claim); stefank@6992: static void keep_alive_oops_do(OopClosure* blk, KlassClosure* klass_closure, bool must_claim); aoqi@0: static void always_strong_oops_do(OopClosure* blk, KlassClosure* klass_closure, bool must_claim); stefank@6992: // cld do stefank@6992: static void cld_do(CLDClosure* cl); stefank@6992: static void roots_cld_do(CLDClosure* strong, CLDClosure* weak); stefank@6992: static void keep_alive_cld_do(CLDClosure* cl); stefank@6992: static void always_strong_cld_do(CLDClosure* cl); stefank@6992: // klass do aoqi@0: static void classes_do(KlassClosure* klass_closure); aoqi@0: static void classes_do(void f(Klass* const)); aoqi@0: static void loaded_classes_do(KlassClosure* klass_closure); aoqi@0: static void classes_unloading_do(void f(Klass* const)); stefank@7333: static bool do_unloading(BoolObjectClosure* is_alive, bool clean_alive); aoqi@0: aoqi@0: // CMS support. aoqi@0: static void remember_new_clds(bool remember) { _saved_head = (remember ? _head : NULL); } aoqi@0: static GrowableArray* new_clds(); aoqi@0: aoqi@0: static void set_should_purge(bool b) { _should_purge = b; } aoqi@0: static void purge_if_needed() { aoqi@0: // Only purge the CLDG for CMS if concurrent sweep is complete. aoqi@0: if (_should_purge) { aoqi@0: purge(); aoqi@0: // reset for next time. aoqi@0: set_should_purge(false); aoqi@0: } aoqi@0: } aoqi@0: stefank@7333: static void free_deallocate_lists(); stefank@7333: aoqi@0: static void dump_on(outputStream * const out) PRODUCT_RETURN; aoqi@0: static void dump() { dump_on(tty); } aoqi@0: static void verify(); aoqi@0: stefank@6992: static bool unload_list_contains(const void* x); aoqi@0: #ifndef PRODUCT aoqi@0: static bool contains_loader_data(ClassLoaderData* loader_data); aoqi@0: #endif aoqi@0: aoqi@0: #if INCLUDE_TRACE aoqi@0: private: aoqi@0: static Ticks _class_unload_time; aoqi@0: static void class_unload_event(Klass* const k); aoqi@0: #endif aoqi@0: }; aoqi@0: aoqi@0: // ClassLoaderData class aoqi@0: aoqi@0: class ClassLoaderData : public CHeapObj { aoqi@0: friend class VMStructs; aoqi@0: private: aoqi@0: class Dependencies VALUE_OBJ_CLASS_SPEC { aoqi@0: objArrayOop _list_head; aoqi@0: void locked_add(objArrayHandle last, aoqi@0: objArrayHandle new_dependency, aoqi@0: Thread* THREAD); aoqi@0: public: aoqi@0: Dependencies() : _list_head(NULL) {} aoqi@0: Dependencies(TRAPS) : _list_head(NULL) { aoqi@0: init(CHECK); aoqi@0: } aoqi@0: void add(Handle dependency, TRAPS); aoqi@0: void init(TRAPS); aoqi@0: void oops_do(OopClosure* f); aoqi@0: }; aoqi@0: aoqi@0: friend class ClassLoaderDataGraph; stefank@6992: friend class ClassLoaderDataGraphKlassIteratorAtomic; aoqi@0: friend class ClassLoaderDataGraphMetaspaceIterator; aoqi@0: friend class MetaDataFactory; aoqi@0: friend class Method; aoqi@0: aoqi@0: static ClassLoaderData * _the_null_class_loader_data; aoqi@0: aoqi@0: oop _class_loader; // oop used to uniquely identify a class loader aoqi@0: // class loader or a canonical class path aoqi@0: Dependencies _dependencies; // holds dependencies from this class loader aoqi@0: // data to others. aoqi@0: aoqi@0: Metaspace * _metaspace; // Meta-space where meta-data defined by the aoqi@0: // classes in the class loader are allocated. aoqi@0: Mutex* _metaspace_lock; // Locks the metaspace for allocations and setup. aoqi@0: bool _unloading; // true if this class loader goes away stefank@6974: bool _keep_alive; // if this CLD is kept alive without a keep_alive_object(). aoqi@0: bool _is_anonymous; // if this CLD is for an anonymous class aoqi@0: volatile int _claimed; // true if claimed, for example during GC traces. aoqi@0: // To avoid applying oop closure more than once. aoqi@0: // Has to be an int because we cas it. aoqi@0: Klass* _klasses; // The classes defined by the class loader. aoqi@0: aoqi@0: JNIHandleBlock* _handles; // Handles to constant pool arrays aoqi@0: aoqi@0: // These method IDs are created for the class loader and set to NULL when the aoqi@0: // class loader is unloaded. They are rarely freed, only for redefine classes aoqi@0: // and if they lose a data race in InstanceKlass. aoqi@0: JNIMethodBlock* _jmethod_ids; aoqi@0: aoqi@0: // Metadata to be deallocated when it's safe at class unloading, when aoqi@0: // this class loader isn't unloaded itself. aoqi@0: GrowableArray* _deallocate_list; aoqi@0: aoqi@0: // Support for walking class loader data objects aoqi@0: ClassLoaderData* _next; /// Next loader_datas created aoqi@0: aoqi@0: // ReadOnly and ReadWrite metaspaces (static because only on the null aoqi@0: // class loader for now). aoqi@0: static Metaspace* _ro_metaspace; aoqi@0: static Metaspace* _rw_metaspace; aoqi@0: aoqi@0: void set_next(ClassLoaderData* next) { _next = next; } aoqi@0: ClassLoaderData* next() const { return _next; } aoqi@0: aoqi@0: ClassLoaderData(Handle h_class_loader, bool is_anonymous, Dependencies dependencies); aoqi@0: ~ClassLoaderData(); aoqi@0: aoqi@0: void set_metaspace(Metaspace* m) { _metaspace = m; } aoqi@0: aoqi@0: JNIHandleBlock* handles() const; aoqi@0: void set_handles(JNIHandleBlock* handles); aoqi@0: aoqi@0: Mutex* metaspace_lock() const { return _metaspace_lock; } aoqi@0: aoqi@0: // GC interface. aoqi@0: void clear_claimed() { _claimed = 0; } aoqi@0: bool claimed() const { return _claimed == 1; } aoqi@0: bool claim(); aoqi@0: aoqi@0: void unload(); aoqi@0: bool keep_alive() const { return _keep_alive; } aoqi@0: void classes_do(void f(Klass*)); aoqi@0: void loaded_classes_do(KlassClosure* klass_closure); aoqi@0: void classes_do(void f(InstanceKlass*)); aoqi@0: aoqi@0: // Deallocate free list during class unloading. aoqi@0: void free_deallocate_list(); aoqi@0: aoqi@0: // Allocate out of this class loader data aoqi@0: MetaWord* allocate(size_t size); aoqi@0: aoqi@0: public: stefank@6992: stefank@6992: bool is_alive(BoolObjectClosure* is_alive_closure) const; stefank@6992: aoqi@0: // Accessors aoqi@0: Metaspace* metaspace_or_null() const { return _metaspace; } aoqi@0: aoqi@0: static ClassLoaderData* the_null_class_loader_data() { aoqi@0: return _the_null_class_loader_data; aoqi@0: } aoqi@0: aoqi@0: bool is_anonymous() const { return _is_anonymous; } aoqi@0: aoqi@0: static void init_null_class_loader_data() { aoqi@0: assert(_the_null_class_loader_data == NULL, "cannot initialize twice"); aoqi@0: assert(ClassLoaderDataGraph::_head == NULL, "cannot initialize twice"); aoqi@0: aoqi@0: // We explicitly initialize the Dependencies object at a later phase in the initialization aoqi@0: _the_null_class_loader_data = new ClassLoaderData((oop)NULL, false, Dependencies()); aoqi@0: ClassLoaderDataGraph::_head = _the_null_class_loader_data; aoqi@0: assert(_the_null_class_loader_data->is_the_null_class_loader_data(), "Must be"); aoqi@0: if (DumpSharedSpaces) { aoqi@0: _the_null_class_loader_data->initialize_shared_metaspaces(); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: bool is_the_null_class_loader_data() const { aoqi@0: return this == _the_null_class_loader_data; aoqi@0: } aoqi@0: bool is_ext_class_loader_data() const; aoqi@0: aoqi@0: // The Metaspace is created lazily so may be NULL. This aoqi@0: // method will allocate a Metaspace if needed. aoqi@0: Metaspace* metaspace_non_null(); aoqi@0: aoqi@0: oop class_loader() const { return _class_loader; } aoqi@0: stefank@6974: // The object the GC is using to keep this ClassLoaderData alive. stefank@6974: oop keep_alive_object() const; stefank@6974: aoqi@0: // Returns true if this class loader data is for a loader going away. aoqi@0: bool is_unloading() const { aoqi@0: assert(!(is_the_null_class_loader_data() && _unloading), "The null class loader can never be unloaded"); aoqi@0: return _unloading; aoqi@0: } stefank@6974: stefank@6974: // Used to make sure that this CLD is not unloaded. aoqi@0: void set_keep_alive(bool value) { _keep_alive = value; } aoqi@0: aoqi@0: unsigned int identity_hash() { aoqi@0: return _class_loader == NULL ? 0 : _class_loader->identity_hash(); aoqi@0: } aoqi@0: aoqi@0: // Used when tracing from klasses. aoqi@0: void oops_do(OopClosure* f, KlassClosure* klass_closure, bool must_claim); aoqi@0: aoqi@0: void classes_do(KlassClosure* klass_closure); aoqi@0: aoqi@0: JNIMethodBlock* jmethod_ids() const { return _jmethod_ids; } aoqi@0: void set_jmethod_ids(JNIMethodBlock* new_block) { _jmethod_ids = new_block; } aoqi@0: aoqi@0: void print_value() { print_value_on(tty); } aoqi@0: void print_value_on(outputStream* out) const; aoqi@0: void dump(outputStream * const out) PRODUCT_RETURN; aoqi@0: void verify(); aoqi@0: const char* loader_name(); aoqi@0: aoqi@0: jobject add_handle(Handle h); aoqi@0: void add_class(Klass* k); aoqi@0: void remove_class(Klass* k); aoqi@0: bool contains_klass(Klass* k); aoqi@0: void record_dependency(Klass* to, TRAPS); aoqi@0: void init_dependencies(TRAPS); aoqi@0: aoqi@0: void add_to_deallocate_list(Metadata* m); aoqi@0: aoqi@0: static ClassLoaderData* class_loader_data(oop loader); aoqi@0: static ClassLoaderData* class_loader_data_or_null(oop loader); aoqi@0: static ClassLoaderData* anonymous_class_loader_data(oop loader, TRAPS); aoqi@0: static void print_loader(ClassLoaderData *loader_data, outputStream *out); aoqi@0: aoqi@0: // CDS support aoqi@0: Metaspace* ro_metaspace(); aoqi@0: Metaspace* rw_metaspace(); aoqi@0: void initialize_shared_metaspaces(); aoqi@0: }; aoqi@0: stefank@6992: // An iterator that distributes Klasses to parallel worker threads. stefank@6992: class ClassLoaderDataGraphKlassIteratorAtomic : public StackObj { asiebenborn@7765: Klass* volatile _next_klass; stefank@6992: public: stefank@6992: ClassLoaderDataGraphKlassIteratorAtomic(); stefank@6992: Klass* next_klass(); stefank@6992: private: stefank@6992: static Klass* next_klass_in_cldg(Klass* klass); stefank@6992: }; stefank@6992: aoqi@0: class ClassLoaderDataGraphMetaspaceIterator : public StackObj { aoqi@0: ClassLoaderData* _data; aoqi@0: public: aoqi@0: ClassLoaderDataGraphMetaspaceIterator(); aoqi@0: ~ClassLoaderDataGraphMetaspaceIterator(); aoqi@0: bool repeat() { return _data != NULL; } aoqi@0: Metaspace* get_next() { aoqi@0: assert(_data != NULL, "Should not be NULL in call to the iterator"); aoqi@0: Metaspace* result = _data->metaspace_or_null(); aoqi@0: _data = _data->next(); aoqi@0: // This result might be NULL for class loaders without metaspace aoqi@0: // yet. It would be nice to return only non-null results but aoqi@0: // there is no guarantee that there will be a non-null result aoqi@0: // down the list so the caller is going to have to check. aoqi@0: return result; aoqi@0: } aoqi@0: }; aoqi@0: #endif // SHARE_VM_CLASSFILE_CLASSLOADERDATA_HPP