< 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 >