|
23 | 23 | */
|
24 | 24 |
|
25 | 25 | #include "precompiled.hpp"
|
| 26 | +#include "classfile/classLoaderData.inline.hpp" |
26 | 27 | #include "classfile/classLoaderDataGraph.inline.hpp"
|
27 | 28 | #include "classfile/dictionary.hpp"
|
28 | 29 | #include "classfile/javaClasses.hpp"
|
@@ -200,9 +201,9 @@ void ClassLoaderDataGraph::walk_metadata_and_clean_metaspaces() {
|
200 | 201 | clean_deallocate_lists(walk_all_metadata);
|
201 | 202 | }
|
202 | 203 |
|
203 |
| -// GC root of class loader data created. |
| 204 | +// List head of all class loader data. |
204 | 205 | ClassLoaderData* volatile ClassLoaderDataGraph::_head = nullptr;
|
205 |
| -ClassLoaderData* ClassLoaderDataGraph::_unloading = nullptr; |
| 206 | +ClassLoaderData* ClassLoaderDataGraph::_unloading_head = nullptr; |
206 | 207 |
|
207 | 208 | bool ClassLoaderDataGraph::_should_clean_deallocate_lists = false;
|
208 | 209 | bool ClassLoaderDataGraph::_safepoint_cleanup_needed = false;
|
@@ -268,16 +269,7 @@ inline void assert_is_safepoint_or_gc() {
|
268 | 269 | "Must be called by safepoint or GC");
|
269 | 270 | }
|
270 | 271 |
|
271 |
| -void ClassLoaderDataGraph::cld_unloading_do(CLDClosure* cl) { |
272 |
| - assert_is_safepoint_or_gc(); |
273 |
| - for (ClassLoaderData* cld = _unloading; cld != nullptr; cld = cld->next()) { |
274 |
| - assert(cld->is_unloading(), "invariant"); |
275 |
| - cl->do_cld(cld); |
276 |
| - } |
277 |
| -} |
278 |
| - |
279 |
| -// These are functions called by the GC, which require all of the CLDs, including the |
280 |
| -// unloading ones. |
| 272 | +// These are functions called by the GC, which require all of the CLDs, including not yet unlinked CLDs. |
281 | 273 | void ClassLoaderDataGraph::cld_do(CLDClosure* cl) {
|
282 | 274 | assert_is_safepoint_or_gc();
|
283 | 275 | for (ClassLoaderData* cld = Atomic::load_acquire(&_head); cld != nullptr; cld = cld->next()) {
|
@@ -430,7 +422,7 @@ void ClassLoaderDataGraph::loaded_classes_do(KlassClosure* klass_closure) {
|
430 | 422 |
|
431 | 423 | void ClassLoaderDataGraph::classes_unloading_do(void f(Klass* const)) {
|
432 | 424 | assert_locked_or_safepoint(ClassLoaderDataGraph_lock);
|
433 |
| - for (ClassLoaderData* cld = _unloading; cld != nullptr; cld = cld->next()) { |
| 425 | + for (ClassLoaderData* cld = _unloading_head; cld != nullptr; cld = cld->unloading_next()) { |
434 | 426 | assert(cld->is_unloading(), "invariant");
|
435 | 427 | cld->classes_do(f);
|
436 | 428 | }
|
@@ -501,37 +493,32 @@ bool ClassLoaderDataGraph::is_valid(ClassLoaderData* loader_data) {
|
501 | 493 | bool ClassLoaderDataGraph::do_unloading() {
|
502 | 494 | assert_locked_or_safepoint(ClassLoaderDataGraph_lock);
|
503 | 495 |
|
504 |
| - ClassLoaderData* data = _head; |
505 | 496 | ClassLoaderData* prev = nullptr;
|
506 | 497 | bool seen_dead_loader = false;
|
507 | 498 | uint loaders_processed = 0;
|
508 | 499 | uint loaders_removed = 0;
|
509 | 500 |
|
510 |
| - data = _head; |
511 |
| - while (data != nullptr) { |
| 501 | + for (ClassLoaderData* data = _head; data != nullptr; data = data->next()) { |
512 | 502 | if (data->is_alive()) {
|
513 | 503 | prev = data;
|
514 |
| - data = data->next(); |
515 | 504 | loaders_processed++;
|
516 |
| - continue; |
517 |
| - } |
518 |
| - seen_dead_loader = true; |
519 |
| - loaders_removed++; |
520 |
| - ClassLoaderData* dead = data; |
521 |
| - dead->unload(); |
522 |
| - data = data->next(); |
523 |
| - // Remove from loader list. |
524 |
| - // This class loader data will no longer be found |
525 |
| - // in the ClassLoaderDataGraph. |
526 |
| - if (prev != nullptr) { |
527 |
| - prev->set_next(data); |
528 | 505 | } else {
|
529 |
| - assert(dead == _head, "sanity check"); |
530 |
| - // The GC might be walking this concurrently |
531 |
| - Atomic::store(&_head, data); |
| 506 | + // Found dead CLD. |
| 507 | + loaders_removed++; |
| 508 | + seen_dead_loader = true; |
| 509 | + data->unload(); |
| 510 | + |
| 511 | + // Move dead CLD to unloading list. |
| 512 | + if (prev != nullptr) { |
| 513 | + prev->unlink_next(); |
| 514 | + } else { |
| 515 | + assert(data == _head, "sanity check"); |
| 516 | + // The GC might be walking this concurrently |
| 517 | + Atomic::store(&_head, data->next()); |
| 518 | + } |
| 519 | + data->set_unloading_next(_unloading_head); |
| 520 | + _unloading_head = data; |
532 | 521 | }
|
533 |
| - dead->set_next(_unloading); |
534 |
| - _unloading = dead; |
535 | 522 | }
|
536 | 523 |
|
537 | 524 | log_debug(class, loader, data)("do_unloading: loaders processed %u, loaders removed %u", loaders_processed, loaders_removed);
|
@@ -563,13 +550,13 @@ void ClassLoaderDataGraph::clean_module_and_package_info() {
|
563 | 550 | }
|
564 | 551 |
|
565 | 552 | void ClassLoaderDataGraph::purge(bool at_safepoint) {
|
566 |
| - ClassLoaderData* list = _unloading; |
567 |
| - _unloading = nullptr; |
| 553 | + ClassLoaderData* list = _unloading_head; |
| 554 | + _unloading_head = nullptr; |
568 | 555 | ClassLoaderData* next = list;
|
569 | 556 | bool classes_unloaded = false;
|
570 | 557 | while (next != nullptr) {
|
571 | 558 | ClassLoaderData* purge_me = next;
|
572 |
| - next = purge_me->next(); |
| 559 | + next = purge_me->unloading_next(); |
573 | 560 | delete purge_me;
|
574 | 561 | classes_unloaded = true;
|
575 | 562 | }
|
|
0 commit comments