comparison src/share/vm/classfile/classLoaderData.cpp @ 9075:ba42fd5e00e6

8010196: NPG: Internal Error: Metaspace allocation lock -- possible deadlock Summary: Refactor the CLD dependency list into a separate class. Use an ObjectLocker to synchronize additions to the CLD dependency list. Reviewed-by: stefank, coleenp
author mgerdin
date Wed, 10 Apr 2013 13:27:35 +0200
parents 16885e702c88
children d587a5c30bd8 c23dbf0e8ab7
comparison
equal deleted inserted replaced
9074:63f57a8c5283 9075:ba42fd5e00e6
68 ClassLoaderData::ClassLoaderData(Handle h_class_loader, bool is_anonymous) : 68 ClassLoaderData::ClassLoaderData(Handle h_class_loader, bool is_anonymous) :
69 _class_loader(h_class_loader()), 69 _class_loader(h_class_loader()),
70 _is_anonymous(is_anonymous), _keep_alive(is_anonymous), // initially 70 _is_anonymous(is_anonymous), _keep_alive(is_anonymous), // initially
71 _metaspace(NULL), _unloading(false), _klasses(NULL), 71 _metaspace(NULL), _unloading(false), _klasses(NULL),
72 _claimed(0), _jmethod_ids(NULL), _handles(NULL), _deallocate_list(NULL), 72 _claimed(0), _jmethod_ids(NULL), _handles(NULL), _deallocate_list(NULL),
73 _next(NULL), _dependencies(NULL), 73 _next(NULL), _dependencies(),
74 _metaspace_lock(new Mutex(Monitor::leaf+1, "Metaspace allocation lock", true)) { 74 _metaspace_lock(new Mutex(Monitor::leaf+1, "Metaspace allocation lock", true)) {
75 // empty 75 // empty
76 } 76 }
77 77
78 void ClassLoaderData::init_dependencies(TRAPS) { 78 void ClassLoaderData::init_dependencies(TRAPS) {
79 _dependencies.init(CHECK);
80 }
81
82 void ClassLoaderData::Dependencies::init(TRAPS) {
79 // Create empty dependencies array to add to. CMS requires this to be 83 // Create empty dependencies array to add to. CMS requires this to be
80 // an oop so that it can track additions via card marks. We think. 84 // an oop so that it can track additions via card marks. We think.
81 _dependencies = (oop)oopFactory::new_objectArray(2, CHECK); 85 _list_head = oopFactory::new_objectArray(2, CHECK);
82 } 86 }
83 87
84 bool ClassLoaderData::claim() { 88 bool ClassLoaderData::claim() {
85 if (_claimed == 1) { 89 if (_claimed == 1) {
86 return false; 90 return false;
93 if (must_claim && !claim()) { 97 if (must_claim && !claim()) {
94 return; 98 return;
95 } 99 }
96 100
97 f->do_oop(&_class_loader); 101 f->do_oop(&_class_loader);
98 f->do_oop(&_dependencies); 102 _dependencies.oops_do(f);
99 _handles->oops_do(f); 103 _handles->oops_do(f);
100 if (klass_closure != NULL) { 104 if (klass_closure != NULL) {
101 classes_do(klass_closure); 105 classes_do(klass_closure);
102 } 106 }
107 }
108
109 void ClassLoaderData::Dependencies::oops_do(OopClosure* f) {
110 f->do_oop((oop*)&_list_head);
103 } 111 }
104 112
105 void ClassLoaderData::classes_do(KlassClosure* klass_closure) { 113 void ClassLoaderData::classes_do(KlassClosure* klass_closure) {
106 for (Klass* k = _klasses; k != NULL; k = k->next_link()) { 114 for (Klass* k = _klasses; k != NULL; k = k->next_link()) {
107 klass_closure->do_klass(k); 115 klass_closure->do_klass(k);
152 } 160 }
153 161
154 // It's a dependency we won't find through GC, add it. This is relatively rare 162 // It's a dependency we won't find through GC, add it. This is relatively rare
155 // Must handle over GC point. 163 // Must handle over GC point.
156 Handle dependency(THREAD, to); 164 Handle dependency(THREAD, to);
157 from_cld->add_dependency(dependency, CHECK); 165 from_cld->_dependencies.add(dependency, CHECK);
158 } 166 }
159 167
160 168
161 void ClassLoaderData::add_dependency(Handle dependency, TRAPS) { 169 void ClassLoaderData::Dependencies::add(Handle dependency, TRAPS) {
162 // Check first if this dependency is already in the list. 170 // Check first if this dependency is already in the list.
163 // Save a pointer to the last to add to under the lock. 171 // Save a pointer to the last to add to under the lock.
164 objArrayOop ok = (objArrayOop)_dependencies; 172 objArrayOop ok = _list_head;
165 objArrayOop last = NULL; 173 objArrayOop last = NULL;
166 while (ok != NULL) { 174 while (ok != NULL) {
167 last = ok; 175 last = ok;
168 if (ok->obj_at(0) == dependency()) { 176 if (ok->obj_at(0) == dependency()) {
169 // Don't need to add it 177 // Don't need to add it
182 190
183 // Must handle over GC points 191 // Must handle over GC points
184 objArrayHandle new_dependency(THREAD, deps); 192 objArrayHandle new_dependency(THREAD, deps);
185 193
186 // Add the dependency under lock 194 // Add the dependency under lock
187 locked_add_dependency(last_handle, new_dependency); 195 locked_add(last_handle, new_dependency, THREAD);
188 } 196 }
189 197
190 void ClassLoaderData::locked_add_dependency(objArrayHandle last_handle, 198 void ClassLoaderData::Dependencies::locked_add(objArrayHandle last_handle,
191 objArrayHandle new_dependency) { 199 objArrayHandle new_dependency,
200 Thread* THREAD) {
192 201
193 // Have to lock and put the new dependency on the end of the dependency 202 // Have to lock and put the new dependency on the end of the dependency
194 // array so the card mark for CMS sees that this dependency is new. 203 // array so the card mark for CMS sees that this dependency is new.
195 // Can probably do this lock free with some effort. 204 // Can probably do this lock free with some effort.
196 MutexLockerEx ml(metaspace_lock(), Mutex::_no_safepoint_check_flag); 205 ObjectLocker ol(Handle(THREAD, _list_head), THREAD);
197 206
198 oop loader_or_mirror = new_dependency->obj_at(0); 207 oop loader_or_mirror = new_dependency->obj_at(0);
199 208
200 // Since the dependencies are only added, add to the end. 209 // Since the dependencies are only added, add to the end.
201 objArrayOop end = last_handle(); 210 objArrayOop end = last_handle();