src/share/vm/classfile/loaderConstraints.cpp

Mon, 27 May 2013 12:58:42 +0200

author
stefank
date
Mon, 27 May 2013 12:58:42 +0200
changeset 5196
8dbc025ff709
parent 4304
90273fc0a981
child 6876
710a3c8b516e
permissions
-rw-r--r--

8015422: Large performance hit when the StringTable is walked twice in Parallel Scavenge
Summary: Combine the calls to StringTable::unlink and StringTable::oops_do in Parallel Scavenge.
Reviewed-by: pliden, coleenp

duke@435 1 /*
coleenp@4037 2 * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
duke@435 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
duke@435 4 *
duke@435 5 * This code is free software; you can redistribute it and/or modify it
duke@435 6 * under the terms of the GNU General Public License version 2 only, as
duke@435 7 * published by the Free Software Foundation.
duke@435 8 *
duke@435 9 * This code is distributed in the hope that it will be useful, but WITHOUT
duke@435 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
duke@435 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
duke@435 12 * version 2 for more details (a copy is included in the LICENSE file that
duke@435 13 * accompanied this code).
duke@435 14 *
duke@435 15 * You should have received a copy of the GNU General Public License version
duke@435 16 * 2 along with this work; if not, write to the Free Software Foundation,
duke@435 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
duke@435 18 *
trims@1907 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
trims@1907 20 * or visit www.oracle.com if you need additional information or have any
trims@1907 21 * questions.
duke@435 22 *
duke@435 23 */
duke@435 24
stefank@2314 25 #include "precompiled.hpp"
coleenp@4037 26 #include "classfile/classLoaderData.inline.hpp"
stefank@2314 27 #include "classfile/loaderConstraints.hpp"
stefank@2314 28 #include "memory/resourceArea.hpp"
stefank@2314 29 #include "oops/oop.inline.hpp"
stefank@2314 30 #include "runtime/handles.inline.hpp"
stefank@2314 31 #include "runtime/safepoint.hpp"
stefank@2314 32 #include "utilities/hashtable.inline.hpp"
duke@435 33
coleenp@4037 34 void LoaderConstraintEntry::set_loader(int i, oop p) {
coleenp@4037 35 set_loader_data(i, ClassLoaderData::class_loader_data(p));
coleenp@4037 36 }
coleenp@4037 37
duke@435 38 LoaderConstraintTable::LoaderConstraintTable(int nof_buckets)
coleenp@4037 39 : Hashtable<Klass*, mtClass>(nof_buckets, sizeof(LoaderConstraintEntry)) {};
duke@435 40
duke@435 41
duke@435 42 LoaderConstraintEntry* LoaderConstraintTable::new_entry(
coleenp@2497 43 unsigned int hash, Symbol* name,
coleenp@4037 44 Klass* klass, int num_loaders,
duke@435 45 int max_loaders) {
duke@435 46 LoaderConstraintEntry* entry;
coleenp@4037 47 entry = (LoaderConstraintEntry*)Hashtable<Klass*, mtClass>::new_entry(hash, klass);
duke@435 48 entry->set_name(name);
duke@435 49 entry->set_num_loaders(num_loaders);
duke@435 50 entry->set_max_loaders(max_loaders);
duke@435 51 return entry;
duke@435 52 }
duke@435 53
coleenp@2497 54 void LoaderConstraintTable::free_entry(LoaderConstraintEntry *entry) {
coleenp@2497 55 // decrement name refcount before freeing
coleenp@2497 56 entry->name()->decrement_refcount();
coleenp@4037 57 Hashtable<Klass*, mtClass>::free_entry(entry);
coleenp@2497 58 }
coleenp@2497 59
coleenp@4037 60 // Enhanced Class Redefinition support
coleenp@4037 61 void LoaderConstraintTable::classes_do(KlassClosure* f) {
duke@435 62 for (int index = 0; index < table_size(); index++) {
duke@435 63 for (LoaderConstraintEntry* probe = bucket(index);
duke@435 64 probe != NULL;
duke@435 65 probe = probe->next()) {
duke@435 66 if (probe->klass() != NULL) {
coleenp@4037 67 f->do_klass(probe->klass());
duke@435 68 }
duke@435 69 }
duke@435 70 }
duke@435 71 }
duke@435 72
duke@435 73 // The loaderConstraintTable must always be accessed with the
duke@435 74 // SystemDictionary lock held. This is true even for readers as
duke@435 75 // entries in the table could be being dynamically resized.
duke@435 76
duke@435 77 LoaderConstraintEntry** LoaderConstraintTable::find_loader_constraint(
coleenp@2497 78 Symbol* name, Handle loader) {
duke@435 79
duke@435 80 unsigned int hash = compute_hash(name);
duke@435 81 int index = hash_to_index(hash);
duke@435 82 LoaderConstraintEntry** pp = bucket_addr(index);
coleenp@4037 83 ClassLoaderData* loader_data = ClassLoaderData::class_loader_data(loader());
coleenp@4037 84
duke@435 85 while (*pp) {
duke@435 86 LoaderConstraintEntry* p = *pp;
duke@435 87 if (p->hash() == hash) {
coleenp@2497 88 if (p->name() == name) {
duke@435 89 for (int i = p->num_loaders() - 1; i >= 0; i--) {
coleenp@4037 90 if (p->loader_data(i) == loader_data) {
duke@435 91 return pp;
duke@435 92 }
duke@435 93 }
duke@435 94 }
duke@435 95 }
duke@435 96 pp = p->next_addr();
duke@435 97 }
duke@435 98 return pp;
duke@435 99 }
duke@435 100
duke@435 101
coleenp@4037 102 void LoaderConstraintTable::purge_loader_constraints() {
jcoomes@1844 103 assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
duke@435 104 // Remove unloaded entries from constraint table
duke@435 105 for (int index = 0; index < table_size(); index++) {
duke@435 106 LoaderConstraintEntry** p = bucket_addr(index);
duke@435 107 while(*p) {
duke@435 108 LoaderConstraintEntry* probe = *p;
coleenp@4037 109 Klass* klass = probe->klass();
duke@435 110 // Remove klass that is no longer alive
coleenp@4037 111 if (klass != NULL &&
coleenp@4037 112 klass->class_loader_data()->is_unloading()) {
duke@435 113 probe->set_klass(NULL);
duke@435 114 if (TraceLoaderConstraints) {
duke@435 115 ResourceMark rm;
duke@435 116 tty->print_cr("[Purging class object from constraint for name %s,"
duke@435 117 " loader list:",
duke@435 118 probe->name()->as_C_string());
duke@435 119 for (int i = 0; i < probe->num_loaders(); i++) {
duke@435 120 tty->print_cr("[ [%d]: %s", i,
coleenp@4304 121 probe->loader_data(i)->loader_name());
duke@435 122 }
duke@435 123 }
duke@435 124 }
duke@435 125 // Remove entries no longer alive from loader array
duke@435 126 int n = 0;
duke@435 127 while (n < probe->num_loaders()) {
coleenp@4037 128 if (probe->loader_data(n)->is_unloading()) {
duke@435 129 if (TraceLoaderConstraints) {
duke@435 130 ResourceMark rm;
duke@435 131 tty->print_cr("[Purging loader %s from constraint for name %s",
coleenp@4304 132 probe->loader_data(n)->loader_name(),
duke@435 133 probe->name()->as_C_string()
duke@435 134 );
duke@435 135 }
duke@435 136
duke@435 137 // Compact array
duke@435 138 int num = probe->num_loaders() - 1;
duke@435 139 probe->set_num_loaders(num);
coleenp@4037 140 probe->set_loader_data(n, probe->loader_data(num));
coleenp@4037 141 probe->set_loader_data(num, NULL);
duke@435 142
duke@435 143 if (TraceLoaderConstraints) {
duke@435 144 ResourceMark rm;
duke@435 145 tty->print_cr("[New loader list:");
duke@435 146 for (int i = 0; i < probe->num_loaders(); i++) {
duke@435 147 tty->print_cr("[ [%d]: %s", i,
coleenp@4304 148 probe->loader_data(i)->loader_name());
duke@435 149 }
duke@435 150 }
duke@435 151
duke@435 152 continue; // current element replaced, so restart without
duke@435 153 // incrementing n
duke@435 154 }
duke@435 155 n++;
duke@435 156 }
duke@435 157 // Check whether entry should be purged
duke@435 158 if (probe->num_loaders() < 2) {
duke@435 159 if (TraceLoaderConstraints) {
duke@435 160 ResourceMark rm;
duke@435 161 tty->print("[Purging complete constraint for name %s\n",
duke@435 162 probe->name()->as_C_string());
duke@435 163 }
duke@435 164
duke@435 165 // Purge entry
duke@435 166 *p = probe->next();
zgu@3900 167 FREE_C_HEAP_ARRAY(oop, probe->loaders(), mtClass);
duke@435 168 free_entry(probe);
duke@435 169 } else {
duke@435 170 #ifdef ASSERT
duke@435 171 if (probe->klass() != NULL) {
coleenp@4037 172 ClassLoaderData* loader_data =
coleenp@4037 173 probe->klass()->class_loader_data();
coleenp@4037 174 assert(!loader_data->is_unloading(), "klass should be live");
duke@435 175 }
duke@435 176 #endif
duke@435 177 // Go to next entry
duke@435 178 p = probe->next_addr();
duke@435 179 }
duke@435 180 }
duke@435 181 }
duke@435 182 }
duke@435 183
coleenp@2497 184 bool LoaderConstraintTable::add_entry(Symbol* class_name,
coleenp@4037 185 Klass* klass1, Handle class_loader1,
coleenp@4037 186 Klass* klass2, Handle class_loader2) {
duke@435 187 int failure_code = 0; // encode different reasons for failing
duke@435 188
duke@435 189 if (klass1 != NULL && klass2 != NULL && klass1 != klass2) {
duke@435 190 failure_code = 1;
duke@435 191 } else {
coleenp@4037 192 Klass* klass = klass1 != NULL ? klass1 : klass2;
duke@435 193
duke@435 194 LoaderConstraintEntry** pp1 = find_loader_constraint(class_name,
duke@435 195 class_loader1);
duke@435 196 if (*pp1 != NULL && (*pp1)->klass() != NULL) {
duke@435 197 if (klass != NULL) {
duke@435 198 if (klass != (*pp1)->klass()) {
duke@435 199 failure_code = 2;
duke@435 200 }
duke@435 201 } else {
duke@435 202 klass = (*pp1)->klass();
duke@435 203 }
duke@435 204 }
duke@435 205
duke@435 206 LoaderConstraintEntry** pp2 = find_loader_constraint(class_name,
duke@435 207 class_loader2);
duke@435 208 if (*pp2 != NULL && (*pp2)->klass() != NULL) {
duke@435 209 if (klass != NULL) {
duke@435 210 if (klass != (*pp2)->klass()) {
duke@435 211 failure_code = 3;
duke@435 212 }
duke@435 213 } else {
duke@435 214 klass = (*pp2)->klass();
duke@435 215 }
duke@435 216 }
duke@435 217
duke@435 218 if (failure_code == 0) {
duke@435 219 if (*pp1 == NULL && *pp2 == NULL) {
duke@435 220 unsigned int hash = compute_hash(class_name);
duke@435 221 int index = hash_to_index(hash);
duke@435 222 LoaderConstraintEntry* p;
coleenp@2497 223 p = new_entry(hash, class_name, klass, 2, 2);
coleenp@4037 224 p->set_loaders(NEW_C_HEAP_ARRAY(ClassLoaderData*, 2, mtClass));
duke@435 225 p->set_loader(0, class_loader1());
duke@435 226 p->set_loader(1, class_loader2());
duke@435 227 p->set_klass(klass);
duke@435 228 p->set_next(bucket(index));
duke@435 229 set_entry(index, p);
duke@435 230 if (TraceLoaderConstraints) {
duke@435 231 ResourceMark rm;
duke@435 232 tty->print("[Adding new constraint for name: %s, loader[0]: %s,"
duke@435 233 " loader[1]: %s ]\n",
coleenp@2497 234 class_name->as_C_string(),
duke@435 235 SystemDictionary::loader_name(class_loader1()),
duke@435 236 SystemDictionary::loader_name(class_loader2())
duke@435 237 );
duke@435 238 }
duke@435 239 } else if (*pp1 == *pp2) {
duke@435 240 /* constraint already imposed */
duke@435 241 if ((*pp1)->klass() == NULL) {
duke@435 242 (*pp1)->set_klass(klass);
duke@435 243 if (TraceLoaderConstraints) {
duke@435 244 ResourceMark rm;
duke@435 245 tty->print("[Setting class object in existing constraint for"
duke@435 246 " name: %s and loader %s ]\n",
coleenp@2497 247 class_name->as_C_string(),
duke@435 248 SystemDictionary::loader_name(class_loader1())
duke@435 249 );
duke@435 250 }
duke@435 251 } else {
duke@435 252 assert((*pp1)->klass() == klass, "loader constraints corrupted");
duke@435 253 }
duke@435 254 } else if (*pp1 == NULL) {
duke@435 255 extend_loader_constraint(*pp2, class_loader1, klass);
duke@435 256 } else if (*pp2 == NULL) {
duke@435 257 extend_loader_constraint(*pp1, class_loader2, klass);
duke@435 258 } else {
duke@435 259 merge_loader_constraints(pp1, pp2, klass);
duke@435 260 }
duke@435 261 }
duke@435 262 }
duke@435 263
duke@435 264 if (failure_code != 0 && TraceLoaderConstraints) {
duke@435 265 ResourceMark rm;
duke@435 266 const char* reason = "";
duke@435 267 switch(failure_code) {
duke@435 268 case 1: reason = "the class objects presented by loader[0] and loader[1]"
duke@435 269 " are different"; break;
duke@435 270 case 2: reason = "the class object presented by loader[0] does not match"
duke@435 271 " the stored class object in the constraint"; break;
duke@435 272 case 3: reason = "the class object presented by loader[1] does not match"
duke@435 273 " the stored class object in the constraint"; break;
duke@435 274 default: reason = "unknown reason code";
duke@435 275 }
duke@435 276 tty->print("[Failed to add constraint for name: %s, loader[0]: %s,"
duke@435 277 " loader[1]: %s, Reason: %s ]\n",
coleenp@2497 278 class_name->as_C_string(),
duke@435 279 SystemDictionary::loader_name(class_loader1()),
duke@435 280 SystemDictionary::loader_name(class_loader2()),
duke@435 281 reason
duke@435 282 );
duke@435 283 }
duke@435 284
duke@435 285 return failure_code == 0;
duke@435 286 }
duke@435 287
duke@435 288
duke@435 289 // return true if the constraint was updated, false if the constraint is
duke@435 290 // violated
duke@435 291 bool LoaderConstraintTable::check_or_update(instanceKlassHandle k,
duke@435 292 Handle loader,
coleenp@2497 293 Symbol* name) {
duke@435 294 LoaderConstraintEntry* p = *(find_loader_constraint(name, loader));
duke@435 295 if (p && p->klass() != NULL && p->klass() != k()) {
duke@435 296 if (TraceLoaderConstraints) {
duke@435 297 ResourceMark rm;
duke@435 298 tty->print("[Constraint check failed for name %s, loader %s: "
duke@435 299 "the presented class object differs from that stored ]\n",
coleenp@2497 300 name->as_C_string(),
duke@435 301 SystemDictionary::loader_name(loader()));
duke@435 302 }
duke@435 303 return false;
duke@435 304 } else {
duke@435 305 if (p && p->klass() == NULL) {
duke@435 306 p->set_klass(k());
duke@435 307 if (TraceLoaderConstraints) {
duke@435 308 ResourceMark rm;
duke@435 309 tty->print("[Updating constraint for name %s, loader %s, "
duke@435 310 "by setting class object ]\n",
coleenp@2497 311 name->as_C_string(),
duke@435 312 SystemDictionary::loader_name(loader()));
duke@435 313 }
duke@435 314 }
duke@435 315 return true;
duke@435 316 }
duke@435 317 }
duke@435 318
coleenp@4037 319 Klass* LoaderConstraintTable::find_constrained_klass(Symbol* name,
duke@435 320 Handle loader) {
duke@435 321 LoaderConstraintEntry *p = *(find_loader_constraint(name, loader));
never@2551 322 if (p != NULL && p->klass() != NULL) {
hseigel@4278 323 if (p->klass()->oop_is_instance() && !InstanceKlass::cast(p->klass())->is_loaded()) {
never@2551 324 // Only return fully loaded classes. Classes found through the
never@2551 325 // constraints might still be in the process of loading.
never@2551 326 return NULL;
never@2551 327 }
duke@435 328 return p->klass();
never@2551 329 }
duke@435 330
duke@435 331 // No constraints, or else no klass loaded yet.
duke@435 332 return NULL;
duke@435 333 }
duke@435 334
duke@435 335 void LoaderConstraintTable::ensure_loader_constraint_capacity(
duke@435 336 LoaderConstraintEntry *p,
duke@435 337 int nfree) {
duke@435 338 if (p->max_loaders() - p->num_loaders() < nfree) {
duke@435 339 int n = nfree + p->num_loaders();
coleenp@4037 340 ClassLoaderData** new_loaders = NEW_C_HEAP_ARRAY(ClassLoaderData*, n, mtClass);
coleenp@4037 341 memcpy(new_loaders, p->loaders(), sizeof(ClassLoaderData*) * p->num_loaders());
duke@435 342 p->set_max_loaders(n);
coleenp@4037 343 FREE_C_HEAP_ARRAY(ClassLoaderData*, p->loaders(), mtClass);
duke@435 344 p->set_loaders(new_loaders);
duke@435 345 }
duke@435 346 }
duke@435 347
duke@435 348
duke@435 349 void LoaderConstraintTable::extend_loader_constraint(LoaderConstraintEntry* p,
duke@435 350 Handle loader,
coleenp@4037 351 Klass* klass) {
duke@435 352 ensure_loader_constraint_capacity(p, 1);
duke@435 353 int num = p->num_loaders();
duke@435 354 p->set_loader(num, loader());
duke@435 355 p->set_num_loaders(num + 1);
duke@435 356 if (TraceLoaderConstraints) {
duke@435 357 ResourceMark rm;
duke@435 358 tty->print("[Extending constraint for name %s by adding loader[%d]: %s %s",
duke@435 359 p->name()->as_C_string(),
duke@435 360 num,
duke@435 361 SystemDictionary::loader_name(loader()),
duke@435 362 (p->klass() == NULL ? " and setting class object ]\n" : " ]\n")
duke@435 363 );
duke@435 364 }
duke@435 365 if (p->klass() == NULL) {
duke@435 366 p->set_klass(klass);
duke@435 367 } else {
duke@435 368 assert(klass == NULL || p->klass() == klass, "constraints corrupted");
duke@435 369 }
duke@435 370 }
duke@435 371
duke@435 372
duke@435 373 void LoaderConstraintTable::merge_loader_constraints(
duke@435 374 LoaderConstraintEntry** pp1,
duke@435 375 LoaderConstraintEntry** pp2,
coleenp@4037 376 Klass* klass) {
duke@435 377 // make sure *pp1 has higher capacity
duke@435 378 if ((*pp1)->max_loaders() < (*pp2)->max_loaders()) {
duke@435 379 LoaderConstraintEntry** tmp = pp2;
duke@435 380 pp2 = pp1;
duke@435 381 pp1 = tmp;
duke@435 382 }
duke@435 383
duke@435 384 LoaderConstraintEntry* p1 = *pp1;
duke@435 385 LoaderConstraintEntry* p2 = *pp2;
duke@435 386
duke@435 387 ensure_loader_constraint_capacity(p1, p2->num_loaders());
duke@435 388
duke@435 389 for (int i = 0; i < p2->num_loaders(); i++) {
duke@435 390 int num = p1->num_loaders();
coleenp@4037 391 p1->set_loader_data(num, p2->loader_data(i));
duke@435 392 p1->set_num_loaders(num + 1);
duke@435 393 }
duke@435 394
duke@435 395 if (TraceLoaderConstraints) {
duke@435 396 ResourceMark rm;
duke@435 397 tty->print_cr("[Merged constraints for name %s, new loader list:",
duke@435 398 p1->name()->as_C_string()
duke@435 399 );
duke@435 400
duke@435 401 for (int i = 0; i < p1->num_loaders(); i++) {
duke@435 402 tty->print_cr("[ [%d]: %s", i,
coleenp@4304 403 p1->loader_data(i)->loader_name());
duke@435 404 }
duke@435 405 if (p1->klass() == NULL) {
duke@435 406 tty->print_cr("[... and setting class object]");
duke@435 407 }
duke@435 408 }
duke@435 409
duke@435 410 // p1->klass() will hold NULL if klass, p2->klass(), and old
duke@435 411 // p1->klass() are all NULL. In addition, all three must have
duke@435 412 // matching non-NULL values, otherwise either the constraints would
duke@435 413 // have been violated, or the constraints had been corrupted (and an
duke@435 414 // assertion would fail).
duke@435 415 if (p2->klass() != NULL) {
duke@435 416 assert(p2->klass() == klass, "constraints corrupted");
duke@435 417 }
duke@435 418 if (p1->klass() == NULL) {
duke@435 419 p1->set_klass(klass);
duke@435 420 } else {
duke@435 421 assert(p1->klass() == klass, "constraints corrupted");
duke@435 422 }
duke@435 423
duke@435 424 *pp2 = p2->next();
zgu@3900 425 FREE_C_HEAP_ARRAY(oop, p2->loaders(), mtClass);
duke@435 426 free_entry(p2);
duke@435 427 return;
duke@435 428 }
duke@435 429
duke@435 430
tonyp@1693 431 void LoaderConstraintTable::verify(Dictionary* dictionary,
tonyp@1693 432 PlaceholderTable* placeholders) {
duke@435 433 Thread *thread = Thread::current();
duke@435 434 for (int cindex = 0; cindex < _loader_constraint_size; cindex++) {
duke@435 435 for (LoaderConstraintEntry* probe = bucket(cindex);
duke@435 436 probe != NULL;
duke@435 437 probe = probe->next()) {
duke@435 438 if (probe->klass() != NULL) {
coleenp@4037 439 InstanceKlass* ik = InstanceKlass::cast(probe->klass());
duke@435 440 guarantee(ik->name() == probe->name(), "name should match");
coleenp@2497 441 Symbol* name = ik->name();
coleenp@4037 442 ClassLoaderData* loader_data = ik->class_loader_data();
coleenp@4037 443 unsigned int d_hash = dictionary->compute_hash(name, loader_data);
duke@435 444 int d_index = dictionary->hash_to_index(d_hash);
coleenp@4037 445 Klass* k = dictionary->find_class(d_index, d_hash, name, loader_data);
tonyp@1693 446 if (k != NULL) {
tonyp@1693 447 // We found the class in the system dictionary, so we should
coleenp@4037 448 // make sure that the Klass* matches what we already have.
tonyp@1693 449 guarantee(k == probe->klass(), "klass should be in dictionary");
tonyp@1693 450 } else {
tonyp@1693 451 // If we don't find the class in the system dictionary, it
tonyp@1693 452 // has to be in the placeholders table.
coleenp@4037 453 unsigned int p_hash = placeholders->compute_hash(name, loader_data);
tonyp@1693 454 int p_index = placeholders->hash_to_index(p_hash);
tonyp@1693 455 PlaceholderEntry* entry = placeholders->get_entry(p_index, p_hash,
coleenp@4037 456 name, loader_data);
tonyp@1693 457
coleenp@4037 458 // The InstanceKlass might not be on the entry, so the only
tonyp@1693 459 // thing we can check here is whether we were successful in
tonyp@1693 460 // finding the class in the placeholders table.
tonyp@1693 461 guarantee(entry != NULL, "klass should be in the placeholders");
tonyp@1693 462 }
duke@435 463 }
duke@435 464 for (int n = 0; n< probe->num_loaders(); n++) {
coleenp@4037 465 assert(ClassLoaderDataGraph::contains_loader_data(probe->loader_data(n)), "The loader is missing");
duke@435 466 }
duke@435 467 }
duke@435 468 }
duke@435 469 }
duke@435 470
duke@435 471 #ifndef PRODUCT
duke@435 472
duke@435 473 // Called with the system dictionary lock held
duke@435 474 void LoaderConstraintTable::print() {
duke@435 475 ResourceMark rm;
duke@435 476
duke@435 477 assert_locked_or_safepoint(SystemDictionary_lock);
duke@435 478 tty->print_cr("Java loader constraints (entries=%d)", _loader_constraint_size);
duke@435 479 for (int cindex = 0; cindex < _loader_constraint_size; cindex++) {
duke@435 480 for (LoaderConstraintEntry* probe = bucket(cindex);
duke@435 481 probe != NULL;
duke@435 482 probe = probe->next()) {
duke@435 483 tty->print("%4d: ", cindex);
duke@435 484 probe->name()->print();
duke@435 485 tty->print(" , loaders:");
duke@435 486 for (int n = 0; n < probe->num_loaders(); n++) {
coleenp@4037 487 probe->loader_data(n)->print_value();
duke@435 488 tty->print(", ");
duke@435 489 }
duke@435 490 tty->cr();
duke@435 491 }
duke@435 492 }
duke@435 493 }
duke@435 494 #endif

mercurial