diff -r caf5eb7dd4a7 -r 882756847a04 hotspot/src/share/vm/classfile/classLoaderData.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/classfile/classLoaderData.hpp Sat Sep 01 13:25:18 2012 -0400 @@ -0,0 +1,257 @@ +/* + * Copyright (c) 2012, 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_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 "runtime/mutex.hpp" +#include "utilities/growableArray.hpp" + +// +// A class loader represents a linkset. Conceptually, a linkset identifies +// the complete transitive closure of resolved links that a dynamic linker can +// produce. +// +// A ClassLoaderData also encapsulates the allocation space, called a metaspace, +// used by the dynamic linker to allocate the runtime representation of all +// the types it defines. +// +// ClassLoaderData are stored in the runtime representation of classes and the +// system dictionary, are roots of garbage collection, and provides iterators +// for root tracing and other GC operations. + +class ClassLoaderData; +class JNIMethodBlock; +class JNIHandleBlock; +class Metadebug; +// GC root for walking class loader data created + +class ClassLoaderDataGraph : public AllStatic { + friend class ClassLoaderData; + 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; + // CMS support. + static ClassLoaderData* _saved_head; + + static ClassLoaderData* add(ClassLoaderData** loader_data_addr, Handle class_loader); + public: + static ClassLoaderData* find_or_create(Handle class_loader); + static void purge(); + static void clear_claimed_marks(); + static void oops_do(OopClosure* f, KlassClosure* klass_closure, bool must_claim); + static void always_strong_oops_do(OopClosure* blk, KlassClosure* klass_closure, bool must_claim); + static void classes_do(KlassClosure* klass_closure); + static bool do_unloading(BoolObjectClosure* is_alive); + + // CMS support. + static void remember_new_clds(bool remember) { _saved_head = (remember ? _head : NULL); } + static GrowableArray* new_clds(); + + static void dump_on(outputStream * const out) PRODUCT_RETURN; + static void dump() { dump_on(tty); } + static void verify(); + +#ifndef PRODUCT + // expensive test for pointer in metaspace for debugging + static bool contains(address x); + static bool contains_loader_data(ClassLoaderData* loader_data); +#endif +}; + +// ClassLoaderData class + +class ClassLoaderData : public CHeapObj { + friend class VMStructs; + private: + friend class ClassLoaderDataGraph; + 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 + Metaspace * _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 + 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. + Klass* _klasses; // The classes defined by the class loader. + + JNIHandleBlock* _handles; // Handles to constant pool arrays + + // These method IDs are created for the class loader and set to NULL when the + // class loader is unloaded. They are rarely freed, only for redefine classes + // and if they lose a data race in InstanceKlass. + JNIMethodBlock* _jmethod_ids; + + // Metadata to be deallocated when it's safe at class unloading, when + // this class loader isn't unloaded itself. + GrowableArray* _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; + + bool has_dependency(ClassLoaderData* cld); + void add_dependency(ClassLoaderData* to_loader_data, TRAPS); + + void set_next(ClassLoaderData* next) { _next = next; } + ClassLoaderData* next() const { return _next; } + + ClassLoaderData(Handle h_class_loader); + ~ClassLoaderData(); + + void set_metaspace(Metaspace* m) { _metaspace = m; } + + JNIHandleBlock* handles() const; + void set_handles(JNIHandleBlock* handles); + + Mutex* metaspace_lock() const { return _metaspace_lock; } + + // GC interface. + void clear_claimed() { _claimed = 0; } + bool claimed() const { return _claimed == 1; } + bool claim(); + + void mark_for_unload() { _unloading = true; } + + void classes_do(void f(InstanceKlass*)); + + // Deallocate free list during class unloading. + void free_deallocate_list(); + + // Allocate out of this class loader data + MetaWord* allocate(size_t size); + + public: + // Accessors + Metaspace* metaspace_or_null() const { return _metaspace; } + + static ClassLoaderData* the_null_class_loader_data() { + return _the_null_class_loader_data; + } + + static void init_null_class_loader_data() { + assert(_the_null_class_loader_data == NULL, "cannot initialize twice"); + assert(ClassLoaderDataGraph::_head == NULL, "cannot initialize twice"); + _the_null_class_loader_data = new ClassLoaderData((oop)NULL); + ClassLoaderDataGraph::_head = _the_null_class_loader_data; + assert(_the_null_class_loader_data->is_the_null_class_loader_data(), "Must be"); + if (DumpSharedSpaces) { + _the_null_class_loader_data->initialize_shared_metaspaces(); + } + } + + bool is_the_null_class_loader_data() const { + return this == _the_null_class_loader_data; + } + + // 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; } + + // 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; + } + + unsigned int identity_hash() { + return _class_loader == NULL ? 0 : _class_loader->identity_hash(); + } + + // Used when tracing from klasses. + void oops_do(OopClosure* f, KlassClosure* klass_closure, bool must_claim); + + void classes_do(KlassClosure* klass_closure); + + bool has_defined(Klass* klass) { + for (Klass* k = _klasses; k != NULL; k = k->next_link()) { + if (klass == k) { + return true; + } + } + return false; + } + + JNIMethodBlock* jmethod_ids() const { return _jmethod_ids; } + void set_jmethod_ids(JNIMethodBlock* new_block) { _jmethod_ids = new_block; } + + void print_value() { print_value_on(tty); } + void print_value_on(outputStream* out) const PRODUCT_RETURN; + void dump(outputStream * const out) PRODUCT_RETURN; + void verify(); + + jobject add_handle(Handle h); + void add_class(Klass* k); + void remove_class(Klass* k); + void record_dependency(Klass* to, TRAPS); + + void add_to_deallocate_list(Metadata* m); + + static ClassLoaderData* class_loader_data(oop loader); + static void print_loader(ClassLoaderData *loader_data, outputStream *out); + + // CDS support + Metaspace* ro_metaspace(); + Metaspace* rw_metaspace(); + void initialize_shared_metaspaces(); +}; + +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(); + // This result might be NULL for class loaders without metaspace + // yet. It would be nice to return only non-null results but + // 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