--- /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<ClassLoaderData*>* 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<mtClass> {
+ 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<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;
+
+ 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