Mercurial > hg > graal-compiler
comparison src/share/vm/classfile/classLoaderData.cpp @ 7185:90273fc0a981
8000662: NPG: nashorn ant clean test262 out-of-memory with Java heap
Summary: Add ClassLoaderData object for each anonymous class with metaspaces to allocate in.
Reviewed-by: twisti, jrose, stefank
author | coleenp |
---|---|
date | Thu, 29 Nov 2012 16:50:29 -0500 |
parents | da91efe96a93 |
children | 30866cd626b0 1b1e16471e46 |
comparison
equal
deleted
inserted
replaced
7181:2fc0334f613a | 7185:90273fc0a981 |
---|---|
63 #include "utilities/ostream.hpp" | 63 #include "utilities/ostream.hpp" |
64 | 64 |
65 ClassLoaderData * ClassLoaderData::_the_null_class_loader_data = NULL; | 65 ClassLoaderData * ClassLoaderData::_the_null_class_loader_data = NULL; |
66 | 66 |
67 ClassLoaderData::ClassLoaderData(Handle h_class_loader) : _class_loader(h_class_loader()), | 67 ClassLoaderData::ClassLoaderData(Handle h_class_loader) : _class_loader(h_class_loader()), |
68 _metaspace(NULL), _unloading(false), _klasses(NULL), | 68 _metaspace(NULL), _unloading(false), _keep_alive(false), _klasses(NULL), |
69 _claimed(0), _jmethod_ids(NULL), _handles(NULL), | 69 _claimed(0), _jmethod_ids(NULL), _handles(NULL), _deallocate_list(NULL), |
70 _deallocate_list(NULL), _next(NULL), | 70 _next(NULL), _dependencies(NULL), |
71 _metaspace_lock(new Mutex(Monitor::leaf+1, "Metaspace allocation lock", true)) { | 71 _metaspace_lock(new Mutex(Monitor::leaf+1, "Metaspace allocation lock", true)) { |
72 // empty | 72 // empty |
73 } | |
74 | |
75 void ClassLoaderData::init_dependencies(TRAPS) { | |
76 // Create empty dependencies array to add to. CMS requires this to be | |
77 // an oop so that it can track additions via card marks. We think. | |
78 _dependencies = (oop)oopFactory::new_objectArray(2, CHECK); | |
73 } | 79 } |
74 | 80 |
75 bool ClassLoaderData::claim() { | 81 bool ClassLoaderData::claim() { |
76 if (_claimed == 1) { | 82 if (_claimed == 1) { |
77 return false; | 83 return false; |
84 if (must_claim && !claim()) { | 90 if (must_claim && !claim()) { |
85 return; | 91 return; |
86 } | 92 } |
87 | 93 |
88 f->do_oop(&_class_loader); | 94 f->do_oop(&_class_loader); |
95 f->do_oop(&_dependencies); | |
89 _handles->oops_do(f); | 96 _handles->oops_do(f); |
90 if (klass_closure != NULL) { | 97 if (klass_closure != NULL) { |
91 classes_do(klass_closure); | 98 classes_do(klass_closure); |
92 } | 99 } |
93 } | 100 } |
108 | 115 |
109 void ClassLoaderData::record_dependency(Klass* k, TRAPS) { | 116 void ClassLoaderData::record_dependency(Klass* k, TRAPS) { |
110 ClassLoaderData * const from_cld = this; | 117 ClassLoaderData * const from_cld = this; |
111 ClassLoaderData * const to_cld = k->class_loader_data(); | 118 ClassLoaderData * const to_cld = k->class_loader_data(); |
112 | 119 |
113 // Records dependency between non-null class loaders only. | 120 // Dependency to the null class loader data doesn't need to be recorded |
114 if (to_cld->is_the_null_class_loader_data() || from_cld->is_the_null_class_loader_data()) { | 121 // because the null class loader data never goes away. |
122 if (to_cld->is_the_null_class_loader_data()) { | |
115 return; | 123 return; |
116 } | 124 } |
117 | 125 |
118 // Check that this dependency isn't from the same or parent class_loader | 126 oop to; |
119 oop to = to_cld->class_loader(); | 127 if (to_cld->is_anonymous()) { |
120 oop from = from_cld->class_loader(); | 128 // Anonymous class dependencies are through the mirror. |
121 | 129 to = k->java_mirror(); |
122 oop curr = from; | 130 } else { |
123 while (curr != NULL) { | 131 to = to_cld->class_loader(); |
124 if (curr == to) { | 132 |
125 return; // this class loader is in the parent list, no need to add it. | 133 // If from_cld is anonymous, even if it's class_loader is a parent of 'to' |
126 } | 134 // we still have to add it. The class_loader won't keep from_cld alive. |
127 curr = java_lang_ClassLoader::parent(curr); | 135 if (!from_cld->is_anonymous()) { |
136 // Check that this dependency isn't from the same or parent class_loader | |
137 oop from = from_cld->class_loader(); | |
138 | |
139 oop curr = from; | |
140 while (curr != NULL) { | |
141 if (curr == to) { | |
142 return; // this class loader is in the parent list, no need to add it. | |
143 } | |
144 curr = java_lang_ClassLoader::parent(curr); | |
145 } | |
146 } | |
128 } | 147 } |
129 | 148 |
130 // It's a dependency we won't find through GC, add it. This is relatively rare | 149 // It's a dependency we won't find through GC, add it. This is relatively rare |
131 from_cld->add_dependency(to_cld, CHECK); | 150 // Must handle over GC point. |
132 } | 151 Handle dependency(THREAD, to); |
133 | 152 from_cld->add_dependency(dependency, CHECK); |
134 bool ClassLoaderData::has_dependency(ClassLoaderData* dependency) { | 153 } |
135 oop loader = dependency->class_loader(); | 154 |
136 | 155 |
137 // Get objArrayOop out of the class_loader oop and see if this dependency | 156 void ClassLoaderData::add_dependency(Handle dependency, TRAPS) { |
138 // is there. Don't safepoint! These are all oops. | 157 // Check first if this dependency is already in the list. |
139 // Dependency list is (oop class_loader, objArrayOop next) | 158 // Save a pointer to the last to add to under the lock. |
140 objArrayOop ok = (objArrayOop)java_lang_ClassLoader::dependencies(class_loader()); | 159 objArrayOop ok = (objArrayOop)_dependencies; |
160 objArrayOop last = NULL; | |
141 while (ok != NULL) { | 161 while (ok != NULL) { |
142 if (ok->obj_at(0) == loader) { | 162 last = ok; |
143 return true; | 163 if (ok->obj_at(0) == dependency()) { |
164 // Don't need to add it | |
165 return; | |
144 } | 166 } |
145 ok = (objArrayOop)ok->obj_at(1); | 167 ok = (objArrayOop)ok->obj_at(1); |
146 } | 168 } |
147 return false; | 169 |
148 } | 170 // Create a new dependency node with fields for (class_loader or mirror, next) |
149 | |
150 void ClassLoaderData::add_dependency(ClassLoaderData* dependency, TRAPS) { | |
151 // Minimize the number of duplicates in the list. | |
152 if (has_dependency(dependency)) { | |
153 return; | |
154 } | |
155 | |
156 // Create a new dependency node with fields for (class_loader, next) | |
157 objArrayOop deps = oopFactory::new_objectArray(2, CHECK); | 171 objArrayOop deps = oopFactory::new_objectArray(2, CHECK); |
158 deps->obj_at_put(0, dependency->class_loader()); | 172 deps->obj_at_put(0, dependency()); |
159 | 173 |
160 // Add this lock free, using compare and exchange, need barriers for GC | 174 // Must handle over more GC points |
161 // Do the barrier first. | 175 objArrayHandle new_dependency(THREAD, deps); |
162 HeapWord* addr = java_lang_ClassLoader::dependencies_addr(class_loader()); | 176 |
163 while (true) { | 177 // Add the dependency under lock |
164 oop old_dependency = java_lang_ClassLoader::dependencies(class_loader()); | 178 assert (last != NULL, "dependencies should be initialized"); |
165 deps->obj_at_put(1, old_dependency); | 179 objArrayHandle last_handle(THREAD, last); |
166 | 180 locked_add_dependency(last_handle, new_dependency); |
167 oop newold = oopDesc::atomic_compare_exchange_oop((oop)deps, addr, old_dependency, true); | 181 } |
168 if (newold == old_dependency) { | 182 |
169 update_barrier_set((void*)addr, (oop)deps); | 183 void ClassLoaderData::locked_add_dependency(objArrayHandle last_handle, |
170 // we won the race to add this dependency | 184 objArrayHandle new_dependency) { |
171 break; | 185 |
172 } | 186 // Have to lock and put the new dependency on the end of the dependency |
173 } | 187 // array so the card mark for CMS sees that this dependency is new. |
174 } | 188 // Can probably do this lock free with some effort. |
175 | 189 MutexLockerEx ml(metaspace_lock(), Mutex::_no_safepoint_check_flag); |
190 | |
191 oop loader_or_mirror = new_dependency->obj_at(0); | |
192 | |
193 // Since the dependencies are only added, add to the end. | |
194 objArrayOop end = last_handle(); | |
195 objArrayOop last = NULL; | |
196 while (end != NULL) { | |
197 last = end; | |
198 // check again if another thread added it to the end. | |
199 if (end->obj_at(0) == loader_or_mirror) { | |
200 // Don't need to add it | |
201 return; | |
202 } | |
203 end = (objArrayOop)end->obj_at(1); | |
204 } | |
205 assert (last != NULL, "dependencies should be initialized"); | |
206 // fill in the first element with the oop in new_dependency. | |
207 if (last->obj_at(0) == NULL) { | |
208 last->obj_at_put(0, new_dependency->obj_at(0)); | |
209 } else { | |
210 last->obj_at_put(1, new_dependency()); | |
211 } | |
212 } | |
176 | 213 |
177 void ClassLoaderDataGraph::clear_claimed_marks() { | 214 void ClassLoaderDataGraph::clear_claimed_marks() { |
178 for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) { | 215 for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) { |
179 cld->clear_claimed(); | 216 cld->clear_claimed(); |
180 } | 217 } |
185 Klass* old_value = _klasses; | 222 Klass* old_value = _klasses; |
186 k->set_next_link(old_value); | 223 k->set_next_link(old_value); |
187 // link the new item into the list | 224 // link the new item into the list |
188 _klasses = k; | 225 _klasses = k; |
189 | 226 |
190 if (TraceClassLoaderData && k->class_loader_data() != NULL) { | 227 if (TraceClassLoaderData && Verbose && k->class_loader_data() != NULL) { |
191 ResourceMark rm; | 228 ResourceMark rm; |
192 tty->print_cr("[TraceClassLoaderData] Adding k: " PTR_FORMAT " %s to CLD: " | 229 tty->print_cr("[TraceClassLoaderData] Adding k: " PTR_FORMAT " %s to CLD: " |
193 PTR_FORMAT " loader: " PTR_FORMAT " %s", | 230 PTR_FORMAT " loader: " PTR_FORMAT " %s", |
194 k, | 231 k, |
195 k->external_name(), | 232 k->external_name(), |
196 k->class_loader_data(), | 233 k->class_loader_data(), |
197 k->class_loader(), | 234 k->class_loader(), |
198 k->class_loader() != NULL ? k->class_loader()->klass()->external_name() : "NULL" | 235 loader_name()); |
199 ); | |
200 } | 236 } |
201 } | 237 } |
202 | 238 |
203 // This is called by InstanceKlass::deallocate_contents() to remove the | 239 // This is called by InstanceKlass::deallocate_contents() to remove the |
204 // scratch_class for redefine classes. We need a lock because there it may not | 240 // scratch_class for redefine classes. We need a lock because there it may not |
219 prev = k; | 255 prev = k; |
220 } | 256 } |
221 ShouldNotReachHere(); // should have found this class!! | 257 ShouldNotReachHere(); // should have found this class!! |
222 } | 258 } |
223 | 259 |
260 | |
261 bool ClassLoaderData::is_anonymous() const { | |
262 Klass* k = _klasses; | |
263 return (_keep_alive || (k != NULL && k->oop_is_instance() && | |
264 InstanceKlass::cast(k)->is_anonymous())); | |
265 } | |
266 | |
267 void ClassLoaderData::unload() { | |
268 _unloading = true; | |
269 | |
270 if (TraceClassLoaderData) { | |
271 ResourceMark rm; | |
272 tty->print("[ClassLoaderData: unload loader data "PTR_FORMAT, this); | |
273 tty->print(" for instance "PTR_FORMAT" of %s", class_loader(), | |
274 loader_name()); | |
275 if (is_anonymous()) { | |
276 tty->print(" for anonymous class "PTR_FORMAT " ", _klasses); | |
277 } | |
278 tty->print_cr("]"); | |
279 } | |
280 } | |
281 | |
282 bool ClassLoaderData::is_alive(BoolObjectClosure* is_alive_closure) const { | |
283 bool alive = | |
284 is_anonymous() ? | |
285 is_alive_closure->do_object_b(_klasses->java_mirror()) : | |
286 class_loader() == NULL || is_alive_closure->do_object_b(class_loader()); | |
287 assert(!alive || claimed(), "must be claimed"); | |
288 return alive; | |
289 } | |
290 | |
291 | |
224 ClassLoaderData::~ClassLoaderData() { | 292 ClassLoaderData::~ClassLoaderData() { |
225 Metaspace *m = _metaspace; | 293 Metaspace *m = _metaspace; |
226 if (m != NULL) { | 294 if (m != NULL) { |
227 _metaspace = NULL; | 295 _metaspace = NULL; |
228 // release the metaspace | 296 // release the metaspace |
261 MutexLockerEx ml(metaspace_lock(), Mutex::_no_safepoint_check_flag); | 329 MutexLockerEx ml(metaspace_lock(), Mutex::_no_safepoint_check_flag); |
262 // Check again if metaspace has been allocated while we were getting this lock. | 330 // Check again if metaspace has been allocated while we were getting this lock. |
263 if (_metaspace != NULL) { | 331 if (_metaspace != NULL) { |
264 return _metaspace; | 332 return _metaspace; |
265 } | 333 } |
266 if (class_loader() == NULL) { | 334 if (this == the_null_class_loader_data()) { |
267 assert(this == the_null_class_loader_data(), "Must be"); | 335 assert (class_loader() == NULL, "Must be"); |
268 size_t word_size = Metaspace::first_chunk_word_size(); | 336 size_t word_size = Metaspace::first_chunk_word_size(); |
269 set_metaspace(new Metaspace(_metaspace_lock, word_size)); | 337 set_metaspace(new Metaspace(_metaspace_lock, word_size)); |
270 } else { | 338 } else { |
271 set_metaspace(new Metaspace(_metaspace_lock)); // default size for now. | 339 set_metaspace(new Metaspace(_metaspace_lock)); // default size for now. |
272 } | 340 } |
323 } | 391 } |
324 } | 392 } |
325 } | 393 } |
326 } | 394 } |
327 | 395 |
396 // These anonymous class loaders are to contain classes used for JSR292 | |
397 ClassLoaderData* ClassLoaderData::anonymous_class_loader_data(oop loader, TRAPS) { | |
398 // Add a new class loader data to the graph. | |
399 ClassLoaderData* cld = ClassLoaderDataGraph::add(NULL, loader, CHECK_NULL); | |
400 return cld; | |
401 } | |
402 | |
403 const char* ClassLoaderData::loader_name() { | |
404 // Handles null class loader | |
405 return SystemDictionary::loader_name(class_loader()); | |
406 } | |
407 | |
328 #ifndef PRODUCT | 408 #ifndef PRODUCT |
329 void ClassLoaderData::print_loader(ClassLoaderData *loader_data, outputStream* out) { | |
330 oop class_loader = loader_data->class_loader(); | |
331 out->print("%s", SystemDictionary::loader_name(class_loader)); | |
332 } | |
333 | |
334 // Define to dump klasses | 409 // Define to dump klasses |
335 #undef CLD_DUMP_KLASSES | 410 #undef CLD_DUMP_KLASSES |
336 | 411 |
337 void ClassLoaderData::dump(outputStream * const out) { | 412 void ClassLoaderData::dump(outputStream * const out) { |
338 ResourceMark rm; | 413 ResourceMark rm; |
339 out->print("ClassLoaderData CLD: "PTR_FORMAT", loader: "PTR_FORMAT", loader_klass: "PTR_FORMAT" %s {", | 414 out->print("ClassLoaderData CLD: "PTR_FORMAT", loader: "PTR_FORMAT", loader_klass: "PTR_FORMAT" %s {", |
340 this, class_loader(), | 415 this, class_loader(), |
341 class_loader() != NULL ? class_loader()->klass() : NULL, | 416 class_loader() != NULL ? class_loader()->klass() : NULL, loader_name()); |
342 class_loader() != NULL ? class_loader()->klass()->external_name() : "NULL"); | |
343 if (claimed()) out->print(" claimed "); | 417 if (claimed()) out->print(" claimed "); |
344 if (is_unloading()) out->print(" unloading "); | 418 if (is_unloading()) out->print(" unloading "); |
345 out->print(" handles " INTPTR_FORMAT, handles()); | 419 out->print(" handles " INTPTR_FORMAT, handles()); |
346 out->cr(); | 420 out->cr(); |
347 if (metaspace_or_null() != NULL) { | 421 if (metaspace_or_null() != NULL) { |
371 #endif // PRODUCT | 445 #endif // PRODUCT |
372 | 446 |
373 void ClassLoaderData::verify() { | 447 void ClassLoaderData::verify() { |
374 oop cl = class_loader(); | 448 oop cl = class_loader(); |
375 | 449 |
376 guarantee(this == class_loader_data(cl), "Must be the same"); | 450 guarantee(this == class_loader_data(cl) || is_anonymous(), "Must be the same"); |
377 guarantee(cl != NULL || this == ClassLoaderData::the_null_class_loader_data(), "must be"); | 451 guarantee(cl != NULL || this == ClassLoaderData::the_null_class_loader_data() || is_anonymous(), "must be"); |
378 | 452 |
379 // Verify the integrity of the allocated space. | 453 // Verify the integrity of the allocated space. |
380 if (metaspace_or_null() != NULL) { | 454 if (metaspace_or_null() != NULL) { |
381 metaspace_or_null()->verify(); | 455 metaspace_or_null()->verify(); |
382 } | 456 } |
384 for (Klass* k = _klasses; k != NULL; k = k->next_link()) { | 458 for (Klass* k = _klasses; k != NULL; k = k->next_link()) { |
385 guarantee(k->class_loader_data() == this, "Must be the same"); | 459 guarantee(k->class_loader_data() == this, "Must be the same"); |
386 k->verify(); | 460 k->verify(); |
387 } | 461 } |
388 } | 462 } |
463 | |
389 | 464 |
390 // GC root of class loader data created. | 465 // GC root of class loader data created. |
391 ClassLoaderData* ClassLoaderDataGraph::_head = NULL; | 466 ClassLoaderData* ClassLoaderDataGraph::_head = NULL; |
392 ClassLoaderData* ClassLoaderDataGraph::_unloading = NULL; | 467 ClassLoaderData* ClassLoaderDataGraph::_unloading = NULL; |
393 ClassLoaderData* ClassLoaderDataGraph::_saved_head = NULL; | 468 ClassLoaderData* ClassLoaderDataGraph::_saved_head = NULL; |
394 | 469 |
395 | 470 |
396 // Add a new class loader data node to the list. Assign the newly created | 471 // Add a new class loader data node to the list. Assign the newly created |
397 // ClassLoaderData into the java/lang/ClassLoader object as a hidden field | 472 // ClassLoaderData into the java/lang/ClassLoader object as a hidden field |
398 ClassLoaderData* ClassLoaderDataGraph::add(ClassLoaderData** cld_addr, Handle loader_data) { | 473 ClassLoaderData* ClassLoaderDataGraph::add(ClassLoaderData** cld_addr, Handle loader, TRAPS) { |
399 // Not assigned a class loader data yet. | 474 // Not assigned a class loader data yet. |
400 // Create one. | 475 // Create one. |
401 ClassLoaderData* *list_head = &_head; | 476 ClassLoaderData* *list_head = &_head; |
402 ClassLoaderData* next = _head; | 477 ClassLoaderData* next = _head; |
403 ClassLoaderData* cld = new ClassLoaderData(loader_data); | 478 ClassLoaderData* cld = new ClassLoaderData(loader); |
404 | 479 |
405 // First, Atomically set it. | 480 if (cld_addr != NULL) { |
406 ClassLoaderData* old = (ClassLoaderData*) Atomic::cmpxchg_ptr(cld, cld_addr, NULL); | 481 // First, Atomically set it |
407 if (old != NULL) { | 482 ClassLoaderData* old = (ClassLoaderData*) Atomic::cmpxchg_ptr(cld, cld_addr, NULL); |
408 delete cld; | 483 if (old != NULL) { |
409 // Returns the data. | 484 delete cld; |
410 return old; | 485 // Returns the data. |
486 return old; | |
487 } | |
488 } else { | |
489 // Disallow unloading for this CLD during initialization if there is no | |
490 // class_loader oop to link this to. | |
491 cld->set_keep_alive(true); | |
411 } | 492 } |
412 | 493 |
413 // We won the race, and therefore the task of adding the data to the list of | 494 // We won the race, and therefore the task of adding the data to the list of |
414 // class loader data | 495 // class loader data |
415 do { | 496 do { |
416 cld->set_next(next); | 497 cld->set_next(next); |
417 ClassLoaderData* exchanged = (ClassLoaderData*)Atomic::cmpxchg_ptr(cld, list_head, next); | 498 ClassLoaderData* exchanged = (ClassLoaderData*)Atomic::cmpxchg_ptr(cld, list_head, next); |
418 if (exchanged == next) { | 499 if (exchanged == next) { |
419 if (TraceClassLoaderData) { | 500 if (TraceClassLoaderData) { |
501 ResourceMark rm; | |
420 tty->print("[ClassLoaderData: "); | 502 tty->print("[ClassLoaderData: "); |
421 tty->print("create class loader data "PTR_FORMAT, cld); | 503 tty->print("create class loader data "PTR_FORMAT, cld); |
422 tty->print(" for instance "PTR_FORMAT" of ", cld->class_loader()); | 504 tty->print(" for instance "PTR_FORMAT" of %s", cld->class_loader(), |
423 loader_data->klass()->name()->print_symbol_on(tty); | 505 cld->loader_name()); |
424 tty->print_cr("]"); | 506 tty->print_cr("]"); |
425 } | 507 } |
508 // Create dependencies after the CLD is added to the list. Otherwise, | |
509 // the GC GC will not find the CLD and the _class_loader field will | |
510 // not be updated. | |
511 cld->init_dependencies(CHECK_NULL); | |
426 return cld; | 512 return cld; |
427 } | 513 } |
428 next = exchanged; | 514 next = exchanged; |
429 } while (true); | 515 } while (true); |
516 | |
430 } | 517 } |
431 | 518 |
432 void ClassLoaderDataGraph::oops_do(OopClosure* f, KlassClosure* klass_closure, bool must_claim) { | 519 void ClassLoaderDataGraph::oops_do(OopClosure* f, KlassClosure* klass_closure, bool must_claim) { |
433 for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) { | 520 for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) { |
434 cld->oops_do(f, klass_closure, must_claim); | 521 cld->oops_do(f, klass_closure, must_claim); |
435 } | 522 } |
436 } | 523 } |
437 | 524 |
525 void ClassLoaderDataGraph::keep_alive_oops_do(OopClosure* f, KlassClosure* klass_closure, bool must_claim) { | |
526 for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) { | |
527 if (cld->keep_alive()) { | |
528 cld->oops_do(f, klass_closure, must_claim); | |
529 } | |
530 } | |
531 } | |
532 | |
438 void ClassLoaderDataGraph::always_strong_oops_do(OopClosure* f, KlassClosure* klass_closure, bool must_claim) { | 533 void ClassLoaderDataGraph::always_strong_oops_do(OopClosure* f, KlassClosure* klass_closure, bool must_claim) { |
439 if (ClassUnloading) { | 534 if (ClassUnloading) { |
440 ClassLoaderData::the_null_class_loader_data()->oops_do(f, klass_closure, must_claim); | 535 ClassLoaderData::the_null_class_loader_data()->oops_do(f, klass_closure, must_claim); |
536 // keep any special CLDs alive. | |
537 ClassLoaderDataGraph::keep_alive_oops_do(f, klass_closure, must_claim); | |
441 } else { | 538 } else { |
442 ClassLoaderDataGraph::oops_do(f, klass_closure, must_claim); | 539 ClassLoaderDataGraph::oops_do(f, klass_closure, must_claim); |
443 } | 540 } |
444 } | 541 } |
445 | 542 |
514 | 611 |
515 return false; | 612 return false; |
516 } | 613 } |
517 #endif // PRODUCT | 614 #endif // PRODUCT |
518 | 615 |
616 | |
519 // Move class loader data from main list to the unloaded list for unloading | 617 // Move class loader data from main list to the unloaded list for unloading |
520 // and deallocation later. | 618 // and deallocation later. |
521 bool ClassLoaderDataGraph::do_unloading(BoolObjectClosure* is_alive) { | 619 bool ClassLoaderDataGraph::do_unloading(BoolObjectClosure* is_alive_closure) { |
522 ClassLoaderData* data = _head; | 620 ClassLoaderData* data = _head; |
523 ClassLoaderData* prev = NULL; | 621 ClassLoaderData* prev = NULL; |
524 bool seen_dead_loader = false; | 622 bool seen_dead_loader = false; |
525 // mark metadata seen on the stack and code cache so we can delete | 623 // mark metadata seen on the stack and code cache so we can delete |
526 // unneeded entries. | 624 // unneeded entries. |
527 bool has_redefined_a_class = JvmtiExport::has_redefined_a_class(); | 625 bool has_redefined_a_class = JvmtiExport::has_redefined_a_class(); |
528 MetadataOnStackMark md_on_stack; | 626 MetadataOnStackMark md_on_stack; |
529 while (data != NULL) { | 627 while (data != NULL) { |
530 if (data->class_loader() == NULL || is_alive->do_object_b(data->class_loader())) { | 628 if (data->keep_alive() || data->is_alive(is_alive_closure)) { |
531 assert(data->claimed(), "class loader data must have been claimed"); | |
532 if (has_redefined_a_class) { | 629 if (has_redefined_a_class) { |
533 data->classes_do(InstanceKlass::purge_previous_versions); | 630 data->classes_do(InstanceKlass::purge_previous_versions); |
534 } | 631 } |
535 data->free_deallocate_list(); | 632 data->free_deallocate_list(); |
536 prev = data; | 633 prev = data; |
537 data = data->next(); | 634 data = data->next(); |
538 continue; | 635 continue; |
539 } | 636 } |
540 seen_dead_loader = true; | 637 seen_dead_loader = true; |
541 ClassLoaderData* dead = data; | 638 ClassLoaderData* dead = data; |
542 dead->mark_for_unload(); | 639 dead->unload(); |
543 if (TraceClassLoaderData) { | |
544 tty->print("[ClassLoaderData: unload loader data "PTR_FORMAT, dead); | |
545 tty->print(" for instance "PTR_FORMAT" of ", dead->class_loader()); | |
546 dead->class_loader()->klass()->name()->print_symbol_on(tty); | |
547 tty->print_cr("]"); | |
548 } | |
549 data = data->next(); | 640 data = data->next(); |
550 // Remove from loader list. | 641 // Remove from loader list. |
551 if (prev != NULL) { | 642 if (prev != NULL) { |
552 prev->set_next(data); | 643 prev->set_next(data); |
553 } else { | 644 } else { |