src/share/vm/classfile/classLoaderData.cpp

changeset 4304
90273fc0a981
parent 4037
da91efe96a93
child 4345
30866cd626b0
child 4353
1b1e16471e46
     1.1 --- a/src/share/vm/classfile/classLoaderData.cpp	Tue Nov 27 14:11:37 2012 -0800
     1.2 +++ b/src/share/vm/classfile/classLoaderData.cpp	Thu Nov 29 16:50:29 2012 -0500
     1.3 @@ -65,13 +65,19 @@
     1.4  ClassLoaderData * ClassLoaderData::_the_null_class_loader_data = NULL;
     1.5  
     1.6  ClassLoaderData::ClassLoaderData(Handle h_class_loader) : _class_loader(h_class_loader()),
     1.7 -  _metaspace(NULL), _unloading(false), _klasses(NULL),
     1.8 -  _claimed(0), _jmethod_ids(NULL), _handles(NULL),
     1.9 -  _deallocate_list(NULL), _next(NULL),
    1.10 +  _metaspace(NULL), _unloading(false), _keep_alive(false), _klasses(NULL),
    1.11 +  _claimed(0), _jmethod_ids(NULL), _handles(NULL), _deallocate_list(NULL),
    1.12 +  _next(NULL), _dependencies(NULL),
    1.13    _metaspace_lock(new Mutex(Monitor::leaf+1, "Metaspace allocation lock", true)) {
    1.14      // empty
    1.15  }
    1.16  
    1.17 +void ClassLoaderData::init_dependencies(TRAPS) {
    1.18 +  // Create empty dependencies array to add to. CMS requires this to be
    1.19 +  // an oop so that it can track additions via card marks.  We think.
    1.20 +  _dependencies = (oop)oopFactory::new_objectArray(2, CHECK);
    1.21 +}
    1.22 +
    1.23  bool ClassLoaderData::claim() {
    1.24    if (_claimed == 1) {
    1.25      return false;
    1.26 @@ -86,6 +92,7 @@
    1.27    }
    1.28  
    1.29    f->do_oop(&_class_loader);
    1.30 +  f->do_oop(&_dependencies);
    1.31    _handles->oops_do(f);
    1.32    if (klass_closure != NULL) {
    1.33      classes_do(klass_closure);
    1.34 @@ -110,70 +117,100 @@
    1.35    ClassLoaderData * const from_cld = this;
    1.36    ClassLoaderData * const to_cld = k->class_loader_data();
    1.37  
    1.38 -  // Records dependency between non-null class loaders only.
    1.39 -  if (to_cld->is_the_null_class_loader_data() || from_cld->is_the_null_class_loader_data()) {
    1.40 +  // Dependency to the null class loader data doesn't need to be recorded
    1.41 +  // because the null class loader data never goes away.
    1.42 +  if (to_cld->is_the_null_class_loader_data()) {
    1.43      return;
    1.44    }
    1.45  
    1.46 -  // Check that this dependency isn't from the same or parent class_loader
    1.47 -  oop to = to_cld->class_loader();
    1.48 -  oop from = from_cld->class_loader();
    1.49 +  oop to;
    1.50 +  if (to_cld->is_anonymous()) {
    1.51 +    // Anonymous class dependencies are through the mirror.
    1.52 +    to = k->java_mirror();
    1.53 +  } else {
    1.54 +    to = to_cld->class_loader();
    1.55  
    1.56 -  oop curr = from;
    1.57 -  while (curr != NULL) {
    1.58 -    if (curr == to) {
    1.59 -      return; // this class loader is in the parent list, no need to add it.
    1.60 +    // If from_cld is anonymous, even if it's class_loader is a parent of 'to'
    1.61 +    // we still have to add it.  The class_loader won't keep from_cld alive.
    1.62 +    if (!from_cld->is_anonymous()) {
    1.63 +      // Check that this dependency isn't from the same or parent class_loader
    1.64 +      oop from = from_cld->class_loader();
    1.65 +
    1.66 +      oop curr = from;
    1.67 +      while (curr != NULL) {
    1.68 +        if (curr == to) {
    1.69 +          return; // this class loader is in the parent list, no need to add it.
    1.70 +        }
    1.71 +        curr = java_lang_ClassLoader::parent(curr);
    1.72 +      }
    1.73      }
    1.74 -    curr = java_lang_ClassLoader::parent(curr);
    1.75    }
    1.76  
    1.77    // It's a dependency we won't find through GC, add it. This is relatively rare
    1.78 -  from_cld->add_dependency(to_cld, CHECK);
    1.79 +  // Must handle over GC point.
    1.80 +  Handle dependency(THREAD, to);
    1.81 +  from_cld->add_dependency(dependency, CHECK);
    1.82  }
    1.83  
    1.84 -bool ClassLoaderData::has_dependency(ClassLoaderData* dependency) {
    1.85 -  oop loader = dependency->class_loader();
    1.86  
    1.87 -  // Get objArrayOop out of the class_loader oop and see if this dependency
    1.88 -  // is there.  Don't safepoint!  These are all oops.
    1.89 -  // Dependency list is (oop class_loader, objArrayOop next)
    1.90 -  objArrayOop ok = (objArrayOop)java_lang_ClassLoader::dependencies(class_loader());
    1.91 +void ClassLoaderData::add_dependency(Handle dependency, TRAPS) {
    1.92 +  // Check first if this dependency is already in the list.
    1.93 +  // Save a pointer to the last to add to under the lock.
    1.94 +  objArrayOop ok = (objArrayOop)_dependencies;
    1.95 +  objArrayOop last = NULL;
    1.96    while (ok != NULL) {
    1.97 -    if (ok->obj_at(0) == loader) {
    1.98 -      return true;
    1.99 +    last = ok;
   1.100 +    if (ok->obj_at(0) == dependency()) {
   1.101 +      // Don't need to add it
   1.102 +      return;
   1.103      }
   1.104      ok = (objArrayOop)ok->obj_at(1);
   1.105    }
   1.106 -  return false;
   1.107 +
   1.108 +  // Create a new dependency node with fields for (class_loader or mirror, next)
   1.109 +  objArrayOop deps = oopFactory::new_objectArray(2, CHECK);
   1.110 +  deps->obj_at_put(0, dependency());
   1.111 +
   1.112 +  // Must handle over more GC points
   1.113 +  objArrayHandle new_dependency(THREAD, deps);
   1.114 +
   1.115 +  // Add the dependency under lock
   1.116 +  assert (last != NULL, "dependencies should be initialized");
   1.117 +  objArrayHandle last_handle(THREAD, last);
   1.118 +  locked_add_dependency(last_handle, new_dependency);
   1.119  }
   1.120  
   1.121 -void ClassLoaderData::add_dependency(ClassLoaderData* dependency, TRAPS) {
   1.122 -  // Minimize the number of duplicates in the list.
   1.123 -  if (has_dependency(dependency)) {
   1.124 -    return;
   1.125 +void ClassLoaderData::locked_add_dependency(objArrayHandle last_handle,
   1.126 +                                            objArrayHandle new_dependency) {
   1.127 +
   1.128 +  // Have to lock and put the new dependency on the end of the dependency
   1.129 +  // array so the card mark for CMS sees that this dependency is new.
   1.130 +  // Can probably do this lock free with some effort.
   1.131 +  MutexLockerEx ml(metaspace_lock(),  Mutex::_no_safepoint_check_flag);
   1.132 +
   1.133 +  oop loader_or_mirror = new_dependency->obj_at(0);
   1.134 +
   1.135 +  // Since the dependencies are only added, add to the end.
   1.136 +  objArrayOop end = last_handle();
   1.137 +  objArrayOop last = NULL;
   1.138 +  while (end != NULL) {
   1.139 +    last = end;
   1.140 +    // check again if another thread added it to the end.
   1.141 +    if (end->obj_at(0) == loader_or_mirror) {
   1.142 +      // Don't need to add it
   1.143 +      return;
   1.144 +    }
   1.145 +    end = (objArrayOop)end->obj_at(1);
   1.146    }
   1.147 -
   1.148 -  // Create a new dependency node with fields for (class_loader, next)
   1.149 -  objArrayOop deps = oopFactory::new_objectArray(2, CHECK);
   1.150 -  deps->obj_at_put(0, dependency->class_loader());
   1.151 -
   1.152 -  // Add this lock free, using compare and exchange, need barriers for GC
   1.153 -  // Do the barrier first.
   1.154 -  HeapWord* addr = java_lang_ClassLoader::dependencies_addr(class_loader());
   1.155 -  while (true) {
   1.156 -    oop old_dependency = java_lang_ClassLoader::dependencies(class_loader());
   1.157 -    deps->obj_at_put(1, old_dependency);
   1.158 -
   1.159 -    oop newold = oopDesc::atomic_compare_exchange_oop((oop)deps, addr, old_dependency, true);
   1.160 -    if (newold == old_dependency) {
   1.161 -      update_barrier_set((void*)addr, (oop)deps);
   1.162 -      // we won the race to add this dependency
   1.163 -      break;
   1.164 -    }
   1.165 +  assert (last != NULL, "dependencies should be initialized");
   1.166 +  // fill in the first element with the oop in new_dependency.
   1.167 +  if (last->obj_at(0) == NULL) {
   1.168 +    last->obj_at_put(0, new_dependency->obj_at(0));
   1.169 +  } else {
   1.170 +    last->obj_at_put(1, new_dependency());
   1.171    }
   1.172  }
   1.173  
   1.174 -
   1.175  void ClassLoaderDataGraph::clear_claimed_marks() {
   1.176    for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) {
   1.177      cld->clear_claimed();
   1.178 @@ -187,7 +224,7 @@
   1.179    // link the new item into the list
   1.180    _klasses = k;
   1.181  
   1.182 -  if (TraceClassLoaderData && k->class_loader_data() != NULL) {
   1.183 +  if (TraceClassLoaderData && Verbose && k->class_loader_data() != NULL) {
   1.184      ResourceMark rm;
   1.185      tty->print_cr("[TraceClassLoaderData] Adding k: " PTR_FORMAT " %s to CLD: "
   1.186                    PTR_FORMAT " loader: " PTR_FORMAT " %s",
   1.187 @@ -195,8 +232,7 @@
   1.188                    k->external_name(),
   1.189                    k->class_loader_data(),
   1.190                    k->class_loader(),
   1.191 -                  k->class_loader() != NULL ? k->class_loader()->klass()->external_name() : "NULL"
   1.192 -      );
   1.193 +                  loader_name());
   1.194    }
   1.195  }
   1.196  
   1.197 @@ -221,6 +257,38 @@
   1.198    ShouldNotReachHere();   // should have found this class!!
   1.199  }
   1.200  
   1.201 +
   1.202 +bool ClassLoaderData::is_anonymous() const {
   1.203 +  Klass* k = _klasses;
   1.204 +  return (_keep_alive || (k != NULL && k->oop_is_instance() &&
   1.205 +          InstanceKlass::cast(k)->is_anonymous()));
   1.206 +}
   1.207 +
   1.208 +void ClassLoaderData::unload() {
   1.209 +  _unloading = true;
   1.210 +
   1.211 +  if (TraceClassLoaderData) {
   1.212 +    ResourceMark rm;
   1.213 +    tty->print("[ClassLoaderData: unload loader data "PTR_FORMAT, this);
   1.214 +    tty->print(" for instance "PTR_FORMAT" of %s", class_loader(),
   1.215 +               loader_name());
   1.216 +    if (is_anonymous()) {
   1.217 +      tty->print(" for anonymous class  "PTR_FORMAT " ", _klasses);
   1.218 +    }
   1.219 +    tty->print_cr("]");
   1.220 +  }
   1.221 +}
   1.222 +
   1.223 +bool ClassLoaderData::is_alive(BoolObjectClosure* is_alive_closure) const {
   1.224 +  bool alive =
   1.225 +    is_anonymous() ?
   1.226 +       is_alive_closure->do_object_b(_klasses->java_mirror()) :
   1.227 +       class_loader() == NULL || is_alive_closure->do_object_b(class_loader());
   1.228 +  assert(!alive || claimed(), "must be claimed");
   1.229 +  return alive;
   1.230 +}
   1.231 +
   1.232 +
   1.233  ClassLoaderData::~ClassLoaderData() {
   1.234    Metaspace *m = _metaspace;
   1.235    if (m != NULL) {
   1.236 @@ -263,8 +331,8 @@
   1.237      if (_metaspace != NULL) {
   1.238        return _metaspace;
   1.239      }
   1.240 -    if (class_loader() == NULL) {
   1.241 -      assert(this == the_null_class_loader_data(), "Must be");
   1.242 +    if (this == the_null_class_loader_data()) {
   1.243 +      assert (class_loader() == NULL, "Must be");
   1.244        size_t word_size = Metaspace::first_chunk_word_size();
   1.245        set_metaspace(new Metaspace(_metaspace_lock, word_size));
   1.246      } else {
   1.247 @@ -325,12 +393,19 @@
   1.248    }
   1.249  }
   1.250  
   1.251 -#ifndef PRODUCT
   1.252 -void ClassLoaderData::print_loader(ClassLoaderData *loader_data, outputStream* out) {
   1.253 -  oop class_loader = loader_data->class_loader();
   1.254 -  out->print("%s", SystemDictionary::loader_name(class_loader));
   1.255 +// These anonymous class loaders are to contain classes used for JSR292
   1.256 +ClassLoaderData* ClassLoaderData::anonymous_class_loader_data(oop loader, TRAPS) {
   1.257 +  // Add a new class loader data to the graph.
   1.258 +  ClassLoaderData* cld = ClassLoaderDataGraph::add(NULL, loader, CHECK_NULL);
   1.259 +  return cld;
   1.260  }
   1.261  
   1.262 +const char* ClassLoaderData::loader_name() {
   1.263 +  // Handles null class loader
   1.264 +  return SystemDictionary::loader_name(class_loader());
   1.265 +}
   1.266 +
   1.267 +#ifndef PRODUCT
   1.268  // Define to dump klasses
   1.269  #undef CLD_DUMP_KLASSES
   1.270  
   1.271 @@ -338,8 +413,7 @@
   1.272    ResourceMark rm;
   1.273    out->print("ClassLoaderData CLD: "PTR_FORMAT", loader: "PTR_FORMAT", loader_klass: "PTR_FORMAT" %s {",
   1.274        this, class_loader(),
   1.275 -      class_loader() != NULL ? class_loader()->klass() : NULL,
   1.276 -      class_loader() != NULL ? class_loader()->klass()->external_name() : "NULL");
   1.277 +      class_loader() != NULL ? class_loader()->klass() : NULL, loader_name());
   1.278    if (claimed()) out->print(" claimed ");
   1.279    if (is_unloading()) out->print(" unloading ");
   1.280    out->print(" handles " INTPTR_FORMAT, handles());
   1.281 @@ -373,8 +447,8 @@
   1.282  void ClassLoaderData::verify() {
   1.283    oop cl = class_loader();
   1.284  
   1.285 -  guarantee(this == class_loader_data(cl), "Must be the same");
   1.286 -  guarantee(cl != NULL || this == ClassLoaderData::the_null_class_loader_data(), "must be");
   1.287 +  guarantee(this == class_loader_data(cl) || is_anonymous(), "Must be the same");
   1.288 +  guarantee(cl != NULL || this == ClassLoaderData::the_null_class_loader_data() || is_anonymous(), "must be");
   1.289  
   1.290    // Verify the integrity of the allocated space.
   1.291    if (metaspace_or_null() != NULL) {
   1.292 @@ -387,6 +461,7 @@
   1.293    }
   1.294  }
   1.295  
   1.296 +
   1.297  // GC root of class loader data created.
   1.298  ClassLoaderData* ClassLoaderDataGraph::_head = NULL;
   1.299  ClassLoaderData* ClassLoaderDataGraph::_unloading = NULL;
   1.300 @@ -395,19 +470,25 @@
   1.301  
   1.302  // Add a new class loader data node to the list.  Assign the newly created
   1.303  // ClassLoaderData into the java/lang/ClassLoader object as a hidden field
   1.304 -ClassLoaderData* ClassLoaderDataGraph::add(ClassLoaderData** cld_addr, Handle loader_data) {
   1.305 +ClassLoaderData* ClassLoaderDataGraph::add(ClassLoaderData** cld_addr, Handle loader, TRAPS) {
   1.306    // Not assigned a class loader data yet.
   1.307    // Create one.
   1.308    ClassLoaderData* *list_head = &_head;
   1.309    ClassLoaderData* next = _head;
   1.310 -  ClassLoaderData* cld = new ClassLoaderData(loader_data);
   1.311 +  ClassLoaderData* cld = new ClassLoaderData(loader);
   1.312  
   1.313 -  // First, Atomically set it.
   1.314 -  ClassLoaderData* old = (ClassLoaderData*) Atomic::cmpxchg_ptr(cld, cld_addr, NULL);
   1.315 -  if (old != NULL) {
   1.316 -    delete cld;
   1.317 -    // Returns the data.
   1.318 -    return old;
   1.319 +  if (cld_addr != NULL) {
   1.320 +    // First, Atomically set it
   1.321 +    ClassLoaderData* old = (ClassLoaderData*) Atomic::cmpxchg_ptr(cld, cld_addr, NULL);
   1.322 +    if (old != NULL) {
   1.323 +      delete cld;
   1.324 +      // Returns the data.
   1.325 +      return old;
   1.326 +    }
   1.327 +  } else {
   1.328 +    // Disallow unloading for this CLD during initialization if there is no
   1.329 +    // class_loader oop to link this to.
   1.330 +    cld->set_keep_alive(true);
   1.331    }
   1.332  
   1.333    // We won the race, and therefore the task of adding the data to the list of
   1.334 @@ -417,16 +498,22 @@
   1.335      ClassLoaderData* exchanged = (ClassLoaderData*)Atomic::cmpxchg_ptr(cld, list_head, next);
   1.336      if (exchanged == next) {
   1.337        if (TraceClassLoaderData) {
   1.338 +        ResourceMark rm;
   1.339          tty->print("[ClassLoaderData: ");
   1.340          tty->print("create class loader data "PTR_FORMAT, cld);
   1.341 -        tty->print(" for instance "PTR_FORMAT" of ", cld->class_loader());
   1.342 -        loader_data->klass()->name()->print_symbol_on(tty);
   1.343 +        tty->print(" for instance "PTR_FORMAT" of %s", cld->class_loader(),
   1.344 +                   cld->loader_name());
   1.345          tty->print_cr("]");
   1.346        }
   1.347 +      // Create dependencies after the CLD is added to the list.  Otherwise,
   1.348 +      // the GC GC will not find the CLD and the _class_loader field will
   1.349 +      // not be updated.
   1.350 +      cld->init_dependencies(CHECK_NULL);
   1.351        return cld;
   1.352      }
   1.353      next = exchanged;
   1.354    } while (true);
   1.355 +
   1.356  }
   1.357  
   1.358  void ClassLoaderDataGraph::oops_do(OopClosure* f, KlassClosure* klass_closure, bool must_claim) {
   1.359 @@ -435,9 +522,19 @@
   1.360    }
   1.361  }
   1.362  
   1.363 +void ClassLoaderDataGraph::keep_alive_oops_do(OopClosure* f, KlassClosure* klass_closure, bool must_claim) {
   1.364 +  for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) {
   1.365 +    if (cld->keep_alive()) {
   1.366 +      cld->oops_do(f, klass_closure, must_claim);
   1.367 +    }
   1.368 +  }
   1.369 +}
   1.370 +
   1.371  void ClassLoaderDataGraph::always_strong_oops_do(OopClosure* f, KlassClosure* klass_closure, bool must_claim) {
   1.372    if (ClassUnloading) {
   1.373      ClassLoaderData::the_null_class_loader_data()->oops_do(f, klass_closure, must_claim);
   1.374 +    // keep any special CLDs alive.
   1.375 +    ClassLoaderDataGraph::keep_alive_oops_do(f, klass_closure, must_claim);
   1.376    } else {
   1.377      ClassLoaderDataGraph::oops_do(f, klass_closure, must_claim);
   1.378    }
   1.379 @@ -516,9 +613,10 @@
   1.380  }
   1.381  #endif // PRODUCT
   1.382  
   1.383 +
   1.384  // Move class loader data from main list to the unloaded list for unloading
   1.385  // and deallocation later.
   1.386 -bool ClassLoaderDataGraph::do_unloading(BoolObjectClosure* is_alive) {
   1.387 +bool ClassLoaderDataGraph::do_unloading(BoolObjectClosure* is_alive_closure) {
   1.388    ClassLoaderData* data = _head;
   1.389    ClassLoaderData* prev = NULL;
   1.390    bool seen_dead_loader = false;
   1.391 @@ -527,8 +625,7 @@
   1.392    bool has_redefined_a_class = JvmtiExport::has_redefined_a_class();
   1.393    MetadataOnStackMark md_on_stack;
   1.394    while (data != NULL) {
   1.395 -    if (data->class_loader() == NULL || is_alive->do_object_b(data->class_loader())) {
   1.396 -      assert(data->claimed(), "class loader data must have been claimed");
   1.397 +    if (data->keep_alive() || data->is_alive(is_alive_closure)) {
   1.398        if (has_redefined_a_class) {
   1.399          data->classes_do(InstanceKlass::purge_previous_versions);
   1.400        }
   1.401 @@ -539,13 +636,7 @@
   1.402      }
   1.403      seen_dead_loader = true;
   1.404      ClassLoaderData* dead = data;
   1.405 -    dead->mark_for_unload();
   1.406 -    if (TraceClassLoaderData) {
   1.407 -      tty->print("[ClassLoaderData: unload loader data "PTR_FORMAT, dead);
   1.408 -      tty->print(" for instance "PTR_FORMAT" of ", dead->class_loader());
   1.409 -      dead->class_loader()->klass()->name()->print_symbol_on(tty);
   1.410 -      tty->print_cr("]");
   1.411 -    }
   1.412 +    dead->unload();
   1.413      data = data->next();
   1.414      // Remove from loader list.
   1.415      if (prev != NULL) {

mercurial