hotspot/src/share/vm/classfile/classLoaderData.hpp
changeset 13728 882756847a04
child 13759 67f8a9de4cdd
--- /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