< prev index next >

src/hotspot/share/classfile/placeholders.cpp

Print this page

 45   }
 46   static unsigned hash(PlaceholderKey const& k) {
 47     return (unsigned) k._name->identity_hash() ^ (int)((intptr_t)k._loader_data >> 3);
 48   }
 49   void print_on(outputStream* st) const;
 50 };
 51 
 52 const int _placeholder_table_size = 503;   // Does this really have to be prime?
 53 using InternalPlaceholderTable = ResourceHashtable<PlaceholderKey, PlaceholderEntry, _placeholder_table_size, AnyObj::C_HEAP, mtClass,
 54                   PlaceholderKey::hash, PlaceholderKey::equals>;
 55 static InternalPlaceholderTable* _placeholders;
 56 
 57 // SeenThread objects represent list of threads that are
 58 // currently performing a load action on a class.
 59 // For class circularity, set before loading a superclass.
 60 // For bootclasssearchpath, set before calling load_instance_class.
 61 // Defining must be single threaded on a class/classloader basis
 62 // For DEFINE_CLASS, the head of the queue owns the
 63 // define token and the rest of the threads wait to return the
 64 // result the first thread gets.


 65 class SeenThread: public CHeapObj<mtInternal> {
 66 private:
 67    JavaThread* _thread;
 68    SeenThread* _stnext;
 69    SeenThread* _stprev;
 70 public:
 71    SeenThread(JavaThread* thread) {
 72        _thread = thread;
 73        _stnext = nullptr;
 74        _stprev = nullptr;
 75    }
 76    JavaThread* thread()          const { return _thread;}
 77    void set_thread(JavaThread* thread) { _thread = thread; }
 78 
 79    SeenThread* next()        const { return _stnext;}
 80    void set_next(SeenThread* seen) { _stnext = seen; }
 81    void set_prev(SeenThread* seen) { _stprev = seen; }
 82 
 83   static void print_action_queue(SeenThread* seen, outputStream* st) {
 84     while (seen != nullptr) {
 85       seen->thread()->print_value_on(st);
 86       st->print(", ");
 87       seen = seen->next();
 88     }
 89   }
 90 };
 91 
 92 SeenThread* PlaceholderEntry::actionToQueue(PlaceholderTable::classloadAction action) {
 93   SeenThread* queuehead = nullptr;
 94   switch (action) {
 95     case PlaceholderTable::LOAD_INSTANCE:
 96        queuehead = _loadInstanceThreadQ;
 97        break;
 98     case PlaceholderTable::LOAD_SUPER:
 99        queuehead = _superThreadQ;
100        break;
101     case PlaceholderTable::DEFINE_CLASS:
102        queuehead = _defineThreadQ;
103        break;
104     default: Unimplemented();
105   }
106   return queuehead;
107 }
108 
109 void PlaceholderEntry::set_threadQ(SeenThread* seenthread, PlaceholderTable::classloadAction action) {
110   switch (action) {
111     case PlaceholderTable::LOAD_INSTANCE:
112        _loadInstanceThreadQ = seenthread;
113        break;
114     case PlaceholderTable::LOAD_SUPER:
115        _superThreadQ = seenthread;
116        break;
117     case PlaceholderTable::DEFINE_CLASS:
118        _defineThreadQ = seenthread;
119        break;
120     default: Unimplemented();
121   }
122   return;
123 }
124 
125 // Doubly-linked list of Threads per action for class/classloader pair
126 // Class circularity support: links in thread before loading superclass
127 // bootstrap loader support:  links in a thread before load_instance_class
128 // definers: use as queue of define requestors, including owner of
129 // define token. Appends for debugging of requestor order
130 void PlaceholderEntry::add_seen_thread(JavaThread* thread, PlaceholderTable::classloadAction action) {
131   assert_lock_strong(SystemDictionary_lock);
132   SeenThread* threadEntry = new SeenThread(thread);
133   SeenThread* seen = actionToQueue(action);
134 
135   if (seen == nullptr) {

171   while (seen) {
172     if (thread == seen->thread()) {
173       if (prev) {
174         prev->set_next(seen->next());
175       } else {
176         set_threadQ(seen->next(), action);
177       }
178       if (seen->next()) {
179         seen->next()->set_prev(prev);
180       }
181       delete seen;
182       break;
183     }
184     prev = seen;
185     seen = seen->next();
186   }
187   return (actionToQueue(action) == nullptr);
188 }
189 
190 
191 void PlaceholderEntry::set_supername(Symbol* supername) {
192   assert_locked_or_safepoint(SystemDictionary_lock);
193   assert(_supername == nullptr || _supername->refcount() > 1, "must be referenced also by the loader");
194   _supername = supername;
195 }
196 
197 // Placeholder objects represent classes currently being loaded.
198 // All threads examining the placeholder table must hold the
199 // SystemDictionary_lock, so we don't need special precautions
200 // on store ordering here.
201 PlaceholderEntry* add_entry(Symbol* class_name, ClassLoaderData* loader_data,
202                             Symbol* supername){
203   assert_locked_or_safepoint(SystemDictionary_lock);
204   assert(class_name != nullptr, "adding nullptr obj");
205 
206   PlaceholderEntry entry;
207   entry.set_supername(supername);
208   PlaceholderKey key(class_name, loader_data);
209   bool created;
210   PlaceholderEntry* table_copy = _placeholders->put_if_absent(key, entry, &created);
211   assert(created, "better be absent");
212   return table_copy;
213 }
214 
215 // Remove a placeholder object.
216 void remove_entry(Symbol* class_name, ClassLoaderData* loader_data) {
217   assert_locked_or_safepoint(SystemDictionary_lock);
218 
219   PlaceholderKey key(class_name, loader_data);
220   _placeholders->remove(key);
221 }
222 
223 
224 PlaceholderEntry* PlaceholderTable::get_entry(Symbol* class_name, ClassLoaderData* loader_data) {
225   assert_locked_or_safepoint(SystemDictionary_lock);
226   PlaceholderKey key(class_name, loader_data);
227   return _placeholders->get(key);
228 }
229 
230 static const char* action_to_string(PlaceholderTable::classloadAction action) {
231   switch (action) {
232   case PlaceholderTable::LOAD_INSTANCE: return "LOAD_INSTANCE";
233   case PlaceholderTable::LOAD_SUPER:    return "LOAD_SUPER";
234   case PlaceholderTable::DEFINE_CLASS:  return "DEFINE_CLASS";
235  }
236  return "";
237 }
238 
239 inline void log(Symbol* name, PlaceholderEntry* entry, const char* function, PlaceholderTable::classloadAction action) {
240   if (log_is_enabled(Debug, class, load, placeholders)) {
241     LogTarget(Debug, class, load, placeholders) lt;
242     ResourceMark rm;
243     LogStream ls(lt);
244     ls.print("entry %s : %s %s ", name->as_C_string(), function, action_to_string(action));
245     entry->print_on(&ls);
246   }
247 }
248 
249 // find_and_add returns probe pointer - old or new
250 // If no entry exists, add a placeholder entry
251 // If entry exists, reuse entry
252 // For both, push SeenThread for classloadAction
253 // If LOAD_SUPER, this is used for circularity detection for instanceklass loading.
254 PlaceholderEntry* PlaceholderTable::find_and_add(Symbol* name,
255                                                  ClassLoaderData* loader_data,
256                                                  classloadAction action,
257                                                  Symbol* supername,
258                                                  JavaThread* thread) {
259   assert(action != LOAD_SUPER || supername != nullptr, "must have a super class name");
260   PlaceholderEntry* probe = get_entry(name, loader_data);
261   if (probe == nullptr) {
262     // Nothing found, add place holder
263     probe = add_entry(name, loader_data, supername);
264   } else {
265     if (action == LOAD_SUPER) {
266       probe->set_supername(supername);
267     }
268   }
269   probe->add_seen_thread(thread, action);
270   log(name, probe, "find_and_add", action);
271   return probe;
272 }
273 
274 void PlaceholderTable::initialize(){
275   _placeholders = new (mtClass) InternalPlaceholderTable();
276 }
277 
278 
279 // placeholder is used to track class loading internal states
280 // superthreadQ tracks class circularity, while loading superclass/superinterface
281 // loadInstanceThreadQ tracks load_instance_class calls
282 // definer() tracks the single thread that owns define token
283 // defineThreadQ tracks waiters on defining thread's results
284 // 1st claimant creates placeholder
285 // find_and_add adds SeenThread entry for appropriate queue
286 // All claimants remove SeenThread after completing action
287 // On removal: if definer and all queues empty, remove entry
288 // Note: you can be in both placeholders and systemDictionary
289 // Therefore - must always check SD first
290 void PlaceholderTable::find_and_remove(Symbol* name, ClassLoaderData* loader_data,
291                                        classloadAction action,
292                                        JavaThread* thread) {
293   assert_locked_or_safepoint(SystemDictionary_lock);
294   PlaceholderEntry* probe = get_entry(name, loader_data);
295   assert(probe != nullptr, "must find an entry");
296   log(name, probe, "find_and_remove", action);
297   probe->remove_seen_thread(thread, action);
298   if (probe->superThreadQ() == nullptr) {
299     probe->set_supername(nullptr);
300   }
301   // If no other threads using this entry, and this thread is not using this entry for other states
302   if ((probe->superThreadQ() == nullptr) && (probe->loadInstanceThreadQ() == nullptr)
303       && (probe->defineThreadQ() == nullptr) && (probe->definer() == nullptr)) {
304     remove_entry(name, loader_data);
305   }
306 }
307 
308 void PlaceholderKey::print_on(outputStream* st) const {
309   _name->print_value_on(st);
310   st->print(", loader ");
311   _loader_data->print_value_on(st);
312 }
313 
314 void PlaceholderEntry::print_on(outputStream* st) const {
315   if (supername() != nullptr) {
316     st->print(", supername ");
317     supername()->print_value_on(st);
318   }
319   if (definer() != nullptr) {
320     st->print(", definer ");
321     definer()->print_value_on(st);
322   }
323   if (instance_klass() != nullptr) {
324     st->print(", InstanceKlass ");
325     instance_klass()->print_value_on(st);
326   }
327   st->cr();
328   st->print("loadInstanceThreadQ threads:");
329   SeenThread::print_action_queue(loadInstanceThreadQ(), st);
330   st->cr();
331   st->print("superThreadQ threads:");
332   SeenThread::print_action_queue(superThreadQ(), st);
333   st->cr();
334   st->print("defineThreadQ threads:");
335   SeenThread::print_action_queue(defineThreadQ(), st);
336   st->cr();
337 }

 45   }
 46   static unsigned hash(PlaceholderKey const& k) {
 47     return (unsigned) k._name->identity_hash() ^ (int)((intptr_t)k._loader_data >> 3);
 48   }
 49   void print_on(outputStream* st) const;
 50 };
 51 
 52 const int _placeholder_table_size = 503;   // Does this really have to be prime?
 53 using InternalPlaceholderTable = ResourceHashtable<PlaceholderKey, PlaceholderEntry, _placeholder_table_size, AnyObj::C_HEAP, mtClass,
 54                   PlaceholderKey::hash, PlaceholderKey::equals>;
 55 static InternalPlaceholderTable* _placeholders;
 56 
 57 // SeenThread objects represent list of threads that are
 58 // currently performing a load action on a class.
 59 // For class circularity, set before loading a superclass.
 60 // For bootclasssearchpath, set before calling load_instance_class.
 61 // Defining must be single threaded on a class/classloader basis
 62 // For DEFINE_CLASS, the head of the queue owns the
 63 // define token and the rest of the threads wait to return the
 64 // result the first thread gets.
 65 // For INLINE_FIELD, set when loading inline type fields for
 66 // class circularity checking.
 67 class SeenThread: public CHeapObj<mtInternal> {
 68 private:
 69    JavaThread* _thread;
 70    SeenThread* _stnext;
 71    SeenThread* _stprev;
 72 public:
 73    SeenThread(JavaThread* thread) {
 74        _thread = thread;
 75        _stnext = nullptr;
 76        _stprev = nullptr;
 77    }
 78    JavaThread* thread()          const { return _thread;}
 79    void set_thread(JavaThread* thread) { _thread = thread; }
 80 
 81    SeenThread* next()        const { return _stnext;}
 82    void set_next(SeenThread* seen) { _stnext = seen; }
 83    void set_prev(SeenThread* seen) { _stprev = seen; }
 84 
 85   static void print_action_queue(SeenThread* seen, outputStream* st) {
 86     while (seen != nullptr) {
 87       seen->thread()->print_value_on(st);
 88       st->print(", ");
 89       seen = seen->next();
 90     }
 91   }
 92 };
 93 
 94 SeenThread* PlaceholderEntry::actionToQueue(PlaceholderTable::classloadAction action) {
 95   SeenThread* queuehead = nullptr;
 96   switch (action) {
 97     case PlaceholderTable::LOAD_INSTANCE:
 98        queuehead = _loadInstanceThreadQ;
 99        break;
100     case PlaceholderTable::DETECT_CIRCULARITY:
101        queuehead = _circularityThreadQ;
102        break;
103     case PlaceholderTable::DEFINE_CLASS:
104        queuehead = _defineThreadQ;
105        break;
106     default: Unimplemented();
107   }
108   return queuehead;
109 }
110 
111 void PlaceholderEntry::set_threadQ(SeenThread* seenthread, PlaceholderTable::classloadAction action) {
112   switch (action) {
113     case PlaceholderTable::LOAD_INSTANCE:
114        _loadInstanceThreadQ = seenthread;
115        break;
116     case PlaceholderTable::DETECT_CIRCULARITY:
117        _circularityThreadQ = seenthread;
118        break;
119     case PlaceholderTable::DEFINE_CLASS:
120        _defineThreadQ = seenthread;
121        break;
122     default: Unimplemented();
123   }
124   return;
125 }
126 
127 // Doubly-linked list of Threads per action for class/classloader pair
128 // Class circularity support: links in thread before loading superclass
129 // bootstrap loader support:  links in a thread before load_instance_class
130 // definers: use as queue of define requestors, including owner of
131 // define token. Appends for debugging of requestor order
132 void PlaceholderEntry::add_seen_thread(JavaThread* thread, PlaceholderTable::classloadAction action) {
133   assert_lock_strong(SystemDictionary_lock);
134   SeenThread* threadEntry = new SeenThread(thread);
135   SeenThread* seen = actionToQueue(action);
136 
137   if (seen == nullptr) {

173   while (seen) {
174     if (thread == seen->thread()) {
175       if (prev) {
176         prev->set_next(seen->next());
177       } else {
178         set_threadQ(seen->next(), action);
179       }
180       if (seen->next()) {
181         seen->next()->set_prev(prev);
182       }
183       delete seen;
184       break;
185     }
186     prev = seen;
187     seen = seen->next();
188   }
189   return (actionToQueue(action) == nullptr);
190 }
191 
192 
193 void PlaceholderEntry::set_next_klass_name(Symbol* next_klass_name) {
194   assert_locked_or_safepoint(SystemDictionary_lock);
195   assert(_next_klass_name == nullptr || _next_klass_name->refcount() > 1, "must be referenced also by the loader");
196   _next_klass_name = next_klass_name;
197 }
198 
199 // Placeholder objects represent classes currently being loaded.
200 // All threads examining the placeholder table must hold the
201 // SystemDictionary_lock, so we don't need special precautions
202 // on store ordering here.
203 PlaceholderEntry* add_entry(Symbol* class_name, ClassLoaderData* loader_data,
204                             Symbol* next_klass_name){
205   assert_locked_or_safepoint(SystemDictionary_lock);
206   assert(class_name != nullptr, "adding nullptr obj");
207 
208   PlaceholderEntry entry;
209   entry.set_next_klass_name(next_klass_name);
210   PlaceholderKey key(class_name, loader_data);
211   bool created;
212   PlaceholderEntry* table_copy = _placeholders->put_if_absent(key, entry, &created);
213   assert(created, "better be absent");
214   return table_copy;
215 }
216 
217 // Remove a placeholder object.
218 void remove_entry(Symbol* class_name, ClassLoaderData* loader_data) {
219   assert_locked_or_safepoint(SystemDictionary_lock);
220 
221   PlaceholderKey key(class_name, loader_data);
222   _placeholders->remove(key);
223 }
224 
225 
226 PlaceholderEntry* PlaceholderTable::get_entry(Symbol* class_name, ClassLoaderData* loader_data) {
227   assert_locked_or_safepoint(SystemDictionary_lock);
228   PlaceholderKey key(class_name, loader_data);
229   return _placeholders->get(key);
230 }
231 
232 static const char* action_to_string(PlaceholderTable::classloadAction action) {
233   switch (action) {
234   case PlaceholderTable::LOAD_INSTANCE: return "LOAD_INSTANCE";
235   case PlaceholderTable::DETECT_CIRCULARITY:    return "DETECT_CIRCULARITY";
236   case PlaceholderTable::DEFINE_CLASS:  return "DEFINE_CLASS";
237  }
238  return "";
239 }
240 
241 inline void log(Symbol* name, PlaceholderEntry* entry, const char* function, PlaceholderTable::classloadAction action) {
242   if (log_is_enabled(Debug, class, load, placeholders)) {
243     LogTarget(Debug, class, load, placeholders) lt;
244     ResourceMark rm;
245     LogStream ls(lt);
246     ls.print("entry %s : %s %s ", name->as_C_string(), function, action_to_string(action));
247     entry->print_on(&ls);
248   }
249 }
250 
251 // find_and_add returns probe pointer - old or new
252 // If no entry exists, add a placeholder entry
253 // If entry exists, reuse entry
254 // For both, push SeenThread for classloadAction
255 // If DETECT_CIRCULARITY, this is used for circularity detection for instanceklass loading.
256 PlaceholderEntry* PlaceholderTable::find_and_add(Symbol* name,
257                                                  ClassLoaderData* loader_data,
258                                                  classloadAction action,
259                                                  Symbol* next_klass_name,
260                                                  JavaThread* thread) {
261   assert(action != DETECT_CIRCULARITY || next_klass_name != nullptr, "must have a super class name");
262   PlaceholderEntry* probe = get_entry(name, loader_data);
263   if (probe == nullptr) {
264     // Nothing found, add place holder
265     probe = add_entry(name, loader_data, next_klass_name);
266   } else {
267     if (action == DETECT_CIRCULARITY) {
268       probe->set_next_klass_name(next_klass_name);
269     }
270   }
271   probe->add_seen_thread(thread, action);
272   log(name, probe, "find_and_add", action);
273   return probe;
274 }
275 
276 void PlaceholderTable::initialize(){
277   _placeholders = new (mtClass) InternalPlaceholderTable();
278 }
279 
280 
281 // placeholder is used to track class loading internal states
282 // superthreadQ tracks class circularity, while loading superclass/superinterface
283 // loadInstanceThreadQ tracks load_instance_class calls
284 // definer() tracks the single thread that owns define token
285 // defineThreadQ tracks waiters on defining thread's results
286 // 1st claimant creates placeholder
287 // find_and_add adds SeenThread entry for appropriate queue
288 // All claimants remove SeenThread after completing action
289 // On removal: if definer and all queues empty, remove entry
290 // Note: you can be in both placeholders and systemDictionary
291 // Therefore - must always check SD first
292 void PlaceholderTable::find_and_remove(Symbol* name, ClassLoaderData* loader_data,
293                                        classloadAction action,
294                                        JavaThread* thread) {
295   assert_locked_or_safepoint(SystemDictionary_lock);
296   PlaceholderEntry* probe = get_entry(name, loader_data);
297   assert(probe != nullptr, "must find an entry");
298   log(name, probe, "find_and_remove", action);
299   probe->remove_seen_thread(thread, action);
300   if (probe->superThreadQ() == nullptr) {
301     probe->set_next_klass_name(nullptr);
302   }
303   // If no other threads using this entry, and this thread is not using this entry for other states
304   if ((probe->superThreadQ() == nullptr) && (probe->loadInstanceThreadQ() == nullptr)
305       && (probe->defineThreadQ() == nullptr) && (probe->definer() == nullptr)) {
306     remove_entry(name, loader_data);
307   }
308 }
309 
310 void PlaceholderKey::print_on(outputStream* st) const {
311   _name->print_value_on(st);
312   st->print(", loader ");
313   _loader_data->print_value_on(st);
314 }
315 
316 void PlaceholderEntry::print_on(outputStream* st) const {
317   if (next_klass_name() != nullptr) {
318     st->print(", next_klass_name ");
319     next_klass_name()->print_value_on(st);
320   }
321   if (definer() != nullptr) {
322     st->print(", definer ");
323     definer()->print_value_on(st);
324   }
325   if (instance_klass() != nullptr) {
326     st->print(", InstanceKlass ");
327     instance_klass()->print_value_on(st);
328   }
329   st->cr();
330   st->print("loadInstanceThreadQ threads:");
331   SeenThread::print_action_queue(loadInstanceThreadQ(), st);
332   st->cr();
333   st->print("superThreadQ threads:");
334   SeenThread::print_action_queue(superThreadQ(), st);
335   st->cr();
336   st->print("defineThreadQ threads:");
337   SeenThread::print_action_queue(defineThreadQ(), st);
338   st->cr();
339 }
< prev index next >