1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/vm/classfile/loaderConstraints.cpp Sat Dec 01 00:00:00 2007 +0000 1.3 @@ -0,0 +1,507 @@ 1.4 +/* 1.5 + * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. 1.11 + * 1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.15 + * version 2 for more details (a copy is included in the LICENSE file that 1.16 + * accompanied this code). 1.17 + * 1.18 + * You should have received a copy of the GNU General Public License version 1.19 + * 2 along with this work; if not, write to the Free Software Foundation, 1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.21 + * 1.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 1.23 + * CA 95054 USA or visit www.sun.com if you need additional information or 1.24 + * have any questions. 1.25 + * 1.26 + */ 1.27 + 1.28 +# include "incls/_precompiled.incl" 1.29 +# include "incls/_loaderConstraints.cpp.incl" 1.30 + 1.31 +LoaderConstraintTable::LoaderConstraintTable(int nof_buckets) 1.32 + : Hashtable(nof_buckets, sizeof(LoaderConstraintEntry)) {}; 1.33 + 1.34 + 1.35 +LoaderConstraintEntry* LoaderConstraintTable::new_entry( 1.36 + unsigned int hash, symbolOop name, 1.37 + klassOop klass, int num_loaders, 1.38 + int max_loaders) { 1.39 + LoaderConstraintEntry* entry; 1.40 + entry = (LoaderConstraintEntry*)Hashtable::new_entry(hash, klass); 1.41 + entry->set_name(name); 1.42 + entry->set_num_loaders(num_loaders); 1.43 + entry->set_max_loaders(max_loaders); 1.44 + return entry; 1.45 +} 1.46 + 1.47 + 1.48 +void LoaderConstraintTable::oops_do(OopClosure* f) { 1.49 + for (int index = 0; index < table_size(); index++) { 1.50 + for (LoaderConstraintEntry* probe = bucket(index); 1.51 + probe != NULL; 1.52 + probe = probe->next()) { 1.53 + f->do_oop((oop*)(probe->name_addr())); 1.54 + if (probe->klass() != NULL) { 1.55 + f->do_oop((oop*)probe->klass_addr()); 1.56 + } 1.57 + for (int n = 0; n < probe->num_loaders(); n++) { 1.58 + if (probe->loader(n) != NULL) { 1.59 + f->do_oop(probe->loader_addr(n)); 1.60 + } 1.61 + } 1.62 + } 1.63 + } 1.64 +} 1.65 + 1.66 +// We must keep the symbolOop used in the name alive. We'll use the 1.67 +// loaders to decide if a particular entry can be purged. 1.68 +void LoaderConstraintTable::always_strong_classes_do(OopClosure* blk) { 1.69 + // We must keep the symbolOop used in the name alive. 1.70 + for (int cindex = 0; cindex < table_size(); cindex++) { 1.71 + for (LoaderConstraintEntry* lc_probe = bucket(cindex); 1.72 + lc_probe != NULL; 1.73 + lc_probe = lc_probe->next()) { 1.74 + assert (lc_probe->name() != NULL, "corrupted loader constraint table"); 1.75 + blk->do_oop((oop*)lc_probe->name_addr()); 1.76 + } 1.77 + } 1.78 +} 1.79 + 1.80 + 1.81 +// The loaderConstraintTable must always be accessed with the 1.82 +// SystemDictionary lock held. This is true even for readers as 1.83 +// entries in the table could be being dynamically resized. 1.84 + 1.85 +LoaderConstraintEntry** LoaderConstraintTable::find_loader_constraint( 1.86 + symbolHandle name, Handle loader) { 1.87 + 1.88 + unsigned int hash = compute_hash(name); 1.89 + int index = hash_to_index(hash); 1.90 + LoaderConstraintEntry** pp = bucket_addr(index); 1.91 + while (*pp) { 1.92 + LoaderConstraintEntry* p = *pp; 1.93 + if (p->hash() == hash) { 1.94 + if (p->name() == name()) { 1.95 + for (int i = p->num_loaders() - 1; i >= 0; i--) { 1.96 + if (p->loader(i) == loader()) { 1.97 + return pp; 1.98 + } 1.99 + } 1.100 + } 1.101 + } 1.102 + pp = p->next_addr(); 1.103 + } 1.104 + return pp; 1.105 +} 1.106 + 1.107 + 1.108 +void LoaderConstraintTable::purge_loader_constraints(BoolObjectClosure* is_alive) { 1.109 + assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint") 1.110 + // Remove unloaded entries from constraint table 1.111 + for (int index = 0; index < table_size(); index++) { 1.112 + LoaderConstraintEntry** p = bucket_addr(index); 1.113 + while(*p) { 1.114 + LoaderConstraintEntry* probe = *p; 1.115 + klassOop klass = probe->klass(); 1.116 + // Remove klass that is no longer alive 1.117 + if (klass != NULL && !is_alive->do_object_b(klass)) { 1.118 + probe->set_klass(NULL); 1.119 + if (TraceLoaderConstraints) { 1.120 + ResourceMark rm; 1.121 + tty->print_cr("[Purging class object from constraint for name %s," 1.122 + " loader list:", 1.123 + probe->name()->as_C_string()); 1.124 + for (int i = 0; i < probe->num_loaders(); i++) { 1.125 + tty->print_cr("[ [%d]: %s", i, 1.126 + SystemDictionary::loader_name(probe->loader(i))); 1.127 + } 1.128 + } 1.129 + } 1.130 + // Remove entries no longer alive from loader array 1.131 + int n = 0; 1.132 + while (n < probe->num_loaders()) { 1.133 + if (probe->loader(n) != NULL) { 1.134 + if (!is_alive->do_object_b(probe->loader(n))) { 1.135 + if (TraceLoaderConstraints) { 1.136 + ResourceMark rm; 1.137 + tty->print_cr("[Purging loader %s from constraint for name %s", 1.138 + SystemDictionary::loader_name(probe->loader(n)), 1.139 + probe->name()->as_C_string() 1.140 + ); 1.141 + } 1.142 + 1.143 + // Compact array 1.144 + int num = probe->num_loaders() - 1; 1.145 + probe->set_num_loaders(num); 1.146 + probe->set_loader(n, probe->loader(num)); 1.147 + probe->set_loader(num, NULL); 1.148 + 1.149 + if (TraceLoaderConstraints) { 1.150 + ResourceMark rm; 1.151 + tty->print_cr("[New loader list:"); 1.152 + for (int i = 0; i < probe->num_loaders(); i++) { 1.153 + tty->print_cr("[ [%d]: %s", i, 1.154 + SystemDictionary::loader_name(probe->loader(i))); 1.155 + } 1.156 + } 1.157 + 1.158 + continue; // current element replaced, so restart without 1.159 + // incrementing n 1.160 + } 1.161 + } 1.162 + n++; 1.163 + } 1.164 + // Check whether entry should be purged 1.165 + if (probe->num_loaders() < 2) { 1.166 + if (TraceLoaderConstraints) { 1.167 + ResourceMark rm; 1.168 + tty->print("[Purging complete constraint for name %s\n", 1.169 + probe->name()->as_C_string()); 1.170 + } 1.171 + 1.172 + // Purge entry 1.173 + *p = probe->next(); 1.174 + FREE_C_HEAP_ARRAY(oop, probe->loaders()); 1.175 + free_entry(probe); 1.176 + } else { 1.177 +#ifdef ASSERT 1.178 + assert(is_alive->do_object_b(probe->name()), "name should be live"); 1.179 + if (probe->klass() != NULL) { 1.180 + assert(is_alive->do_object_b(probe->klass()), "klass should be live"); 1.181 + } 1.182 + for (n = 0; n < probe->num_loaders(); n++) { 1.183 + if (probe->loader(n) != NULL) { 1.184 + assert(is_alive->do_object_b(probe->loader(n)), "loader should be live"); 1.185 + } 1.186 + } 1.187 +#endif 1.188 + // Go to next entry 1.189 + p = probe->next_addr(); 1.190 + } 1.191 + } 1.192 + } 1.193 +} 1.194 + 1.195 +bool LoaderConstraintTable::add_entry(symbolHandle class_name, 1.196 + klassOop klass1, Handle class_loader1, 1.197 + klassOop klass2, Handle class_loader2) { 1.198 + int failure_code = 0; // encode different reasons for failing 1.199 + 1.200 + if (klass1 != NULL && klass2 != NULL && klass1 != klass2) { 1.201 + failure_code = 1; 1.202 + } else { 1.203 + klassOop klass = klass1 != NULL ? klass1 : klass2; 1.204 + 1.205 + LoaderConstraintEntry** pp1 = find_loader_constraint(class_name, 1.206 + class_loader1); 1.207 + if (*pp1 != NULL && (*pp1)->klass() != NULL) { 1.208 + if (klass != NULL) { 1.209 + if (klass != (*pp1)->klass()) { 1.210 + failure_code = 2; 1.211 + } 1.212 + } else { 1.213 + klass = (*pp1)->klass(); 1.214 + } 1.215 + } 1.216 + 1.217 + LoaderConstraintEntry** pp2 = find_loader_constraint(class_name, 1.218 + class_loader2); 1.219 + if (*pp2 != NULL && (*pp2)->klass() != NULL) { 1.220 + if (klass != NULL) { 1.221 + if (klass != (*pp2)->klass()) { 1.222 + failure_code = 3; 1.223 + } 1.224 + } else { 1.225 + klass = (*pp2)->klass(); 1.226 + } 1.227 + } 1.228 + 1.229 + if (failure_code == 0) { 1.230 + if (*pp1 == NULL && *pp2 == NULL) { 1.231 + unsigned int hash = compute_hash(class_name); 1.232 + int index = hash_to_index(hash); 1.233 + LoaderConstraintEntry* p; 1.234 + p = new_entry(hash, class_name(), klass, 2, 2); 1.235 + p->set_loaders(NEW_C_HEAP_ARRAY(oop, 2)); 1.236 + p->set_loader(0, class_loader1()); 1.237 + p->set_loader(1, class_loader2()); 1.238 + p->set_klass(klass); 1.239 + p->set_next(bucket(index)); 1.240 + set_entry(index, p); 1.241 + if (TraceLoaderConstraints) { 1.242 + ResourceMark rm; 1.243 + tty->print("[Adding new constraint for name: %s, loader[0]: %s," 1.244 + " loader[1]: %s ]\n", 1.245 + class_name()->as_C_string(), 1.246 + SystemDictionary::loader_name(class_loader1()), 1.247 + SystemDictionary::loader_name(class_loader2()) 1.248 + ); 1.249 + } 1.250 + } else if (*pp1 == *pp2) { 1.251 + /* constraint already imposed */ 1.252 + if ((*pp1)->klass() == NULL) { 1.253 + (*pp1)->set_klass(klass); 1.254 + if (TraceLoaderConstraints) { 1.255 + ResourceMark rm; 1.256 + tty->print("[Setting class object in existing constraint for" 1.257 + " name: %s and loader %s ]\n", 1.258 + class_name()->as_C_string(), 1.259 + SystemDictionary::loader_name(class_loader1()) 1.260 + ); 1.261 + } 1.262 + } else { 1.263 + assert((*pp1)->klass() == klass, "loader constraints corrupted"); 1.264 + } 1.265 + } else if (*pp1 == NULL) { 1.266 + extend_loader_constraint(*pp2, class_loader1, klass); 1.267 + } else if (*pp2 == NULL) { 1.268 + extend_loader_constraint(*pp1, class_loader2, klass); 1.269 + } else { 1.270 + merge_loader_constraints(pp1, pp2, klass); 1.271 + } 1.272 + } 1.273 + } 1.274 + 1.275 + if (failure_code != 0 && TraceLoaderConstraints) { 1.276 + ResourceMark rm; 1.277 + const char* reason = ""; 1.278 + switch(failure_code) { 1.279 + case 1: reason = "the class objects presented by loader[0] and loader[1]" 1.280 + " are different"; break; 1.281 + case 2: reason = "the class object presented by loader[0] does not match" 1.282 + " the stored class object in the constraint"; break; 1.283 + case 3: reason = "the class object presented by loader[1] does not match" 1.284 + " the stored class object in the constraint"; break; 1.285 + default: reason = "unknown reason code"; 1.286 + } 1.287 + tty->print("[Failed to add constraint for name: %s, loader[0]: %s," 1.288 + " loader[1]: %s, Reason: %s ]\n", 1.289 + class_name()->as_C_string(), 1.290 + SystemDictionary::loader_name(class_loader1()), 1.291 + SystemDictionary::loader_name(class_loader2()), 1.292 + reason 1.293 + ); 1.294 + } 1.295 + 1.296 + return failure_code == 0; 1.297 +} 1.298 + 1.299 + 1.300 +// return true if the constraint was updated, false if the constraint is 1.301 +// violated 1.302 +bool LoaderConstraintTable::check_or_update(instanceKlassHandle k, 1.303 + Handle loader, 1.304 + symbolHandle name) { 1.305 + LoaderConstraintEntry* p = *(find_loader_constraint(name, loader)); 1.306 + if (p && p->klass() != NULL && p->klass() != k()) { 1.307 + if (TraceLoaderConstraints) { 1.308 + ResourceMark rm; 1.309 + tty->print("[Constraint check failed for name %s, loader %s: " 1.310 + "the presented class object differs from that stored ]\n", 1.311 + name()->as_C_string(), 1.312 + SystemDictionary::loader_name(loader())); 1.313 + } 1.314 + return false; 1.315 + } else { 1.316 + if (p && p->klass() == NULL) { 1.317 + p->set_klass(k()); 1.318 + if (TraceLoaderConstraints) { 1.319 + ResourceMark rm; 1.320 + tty->print("[Updating constraint for name %s, loader %s, " 1.321 + "by setting class object ]\n", 1.322 + name()->as_C_string(), 1.323 + SystemDictionary::loader_name(loader())); 1.324 + } 1.325 + } 1.326 + return true; 1.327 + } 1.328 +} 1.329 + 1.330 +klassOop LoaderConstraintTable::find_constrained_klass(symbolHandle name, 1.331 + Handle loader) { 1.332 + LoaderConstraintEntry *p = *(find_loader_constraint(name, loader)); 1.333 + if (p != NULL && p->klass() != NULL) 1.334 + return p->klass(); 1.335 + 1.336 + // No constraints, or else no klass loaded yet. 1.337 + return NULL; 1.338 +} 1.339 + 1.340 + 1.341 +klassOop LoaderConstraintTable::find_constrained_elem_klass(symbolHandle name, 1.342 + symbolHandle elem_name, 1.343 + Handle loader, 1.344 + TRAPS) { 1.345 + LoaderConstraintEntry *p = *(find_loader_constraint(name, loader)); 1.346 + if (p != NULL) { 1.347 + assert(p->klass() == NULL, "Expecting null array klass"); 1.348 + 1.349 + // The array name has a constraint, but it will not have a class. Check 1.350 + // each loader for an associated elem 1.351 + for (int i = 0; i < p->num_loaders(); i++) { 1.352 + Handle no_protection_domain; 1.353 + 1.354 + klassOop k = SystemDictionary::find(elem_name, p->loader(i), no_protection_domain, THREAD); 1.355 + if (k != NULL) { 1.356 + // Return the first elem klass found. 1.357 + return k; 1.358 + } 1.359 + } 1.360 + } 1.361 + 1.362 + // No constraints, or else no klass loaded yet. 1.363 + return NULL; 1.364 +} 1.365 + 1.366 + 1.367 +void LoaderConstraintTable::ensure_loader_constraint_capacity( 1.368 + LoaderConstraintEntry *p, 1.369 + int nfree) { 1.370 + if (p->max_loaders() - p->num_loaders() < nfree) { 1.371 + int n = nfree + p->num_loaders(); 1.372 + oop* new_loaders = NEW_C_HEAP_ARRAY(oop, n); 1.373 + memcpy(new_loaders, p->loaders(), sizeof(oop) * p->num_loaders()); 1.374 + p->set_max_loaders(n); 1.375 + FREE_C_HEAP_ARRAY(oop, p->loaders()); 1.376 + p->set_loaders(new_loaders); 1.377 + } 1.378 +} 1.379 + 1.380 + 1.381 +void LoaderConstraintTable::extend_loader_constraint(LoaderConstraintEntry* p, 1.382 + Handle loader, 1.383 + klassOop klass) { 1.384 + ensure_loader_constraint_capacity(p, 1); 1.385 + int num = p->num_loaders(); 1.386 + p->set_loader(num, loader()); 1.387 + p->set_num_loaders(num + 1); 1.388 + if (TraceLoaderConstraints) { 1.389 + ResourceMark rm; 1.390 + tty->print("[Extending constraint for name %s by adding loader[%d]: %s %s", 1.391 + p->name()->as_C_string(), 1.392 + num, 1.393 + SystemDictionary::loader_name(loader()), 1.394 + (p->klass() == NULL ? " and setting class object ]\n" : " ]\n") 1.395 + ); 1.396 + } 1.397 + if (p->klass() == NULL) { 1.398 + p->set_klass(klass); 1.399 + } else { 1.400 + assert(klass == NULL || p->klass() == klass, "constraints corrupted"); 1.401 + } 1.402 +} 1.403 + 1.404 + 1.405 +void LoaderConstraintTable::merge_loader_constraints( 1.406 + LoaderConstraintEntry** pp1, 1.407 + LoaderConstraintEntry** pp2, 1.408 + klassOop klass) { 1.409 + // make sure *pp1 has higher capacity 1.410 + if ((*pp1)->max_loaders() < (*pp2)->max_loaders()) { 1.411 + LoaderConstraintEntry** tmp = pp2; 1.412 + pp2 = pp1; 1.413 + pp1 = tmp; 1.414 + } 1.415 + 1.416 + LoaderConstraintEntry* p1 = *pp1; 1.417 + LoaderConstraintEntry* p2 = *pp2; 1.418 + 1.419 + ensure_loader_constraint_capacity(p1, p2->num_loaders()); 1.420 + 1.421 + for (int i = 0; i < p2->num_loaders(); i++) { 1.422 + int num = p1->num_loaders(); 1.423 + p1->set_loader(num, p2->loader(i)); 1.424 + p1->set_num_loaders(num + 1); 1.425 + } 1.426 + 1.427 + if (TraceLoaderConstraints) { 1.428 + ResourceMark rm; 1.429 + tty->print_cr("[Merged constraints for name %s, new loader list:", 1.430 + p1->name()->as_C_string() 1.431 + ); 1.432 + 1.433 + for (int i = 0; i < p1->num_loaders(); i++) { 1.434 + tty->print_cr("[ [%d]: %s", i, 1.435 + SystemDictionary::loader_name(p1->loader(i))); 1.436 + } 1.437 + if (p1->klass() == NULL) { 1.438 + tty->print_cr("[... and setting class object]"); 1.439 + } 1.440 + } 1.441 + 1.442 + // p1->klass() will hold NULL if klass, p2->klass(), and old 1.443 + // p1->klass() are all NULL. In addition, all three must have 1.444 + // matching non-NULL values, otherwise either the constraints would 1.445 + // have been violated, or the constraints had been corrupted (and an 1.446 + // assertion would fail). 1.447 + if (p2->klass() != NULL) { 1.448 + assert(p2->klass() == klass, "constraints corrupted"); 1.449 + } 1.450 + if (p1->klass() == NULL) { 1.451 + p1->set_klass(klass); 1.452 + } else { 1.453 + assert(p1->klass() == klass, "constraints corrupted"); 1.454 + } 1.455 + 1.456 + *pp2 = p2->next(); 1.457 + FREE_C_HEAP_ARRAY(oop, p2->loaders()); 1.458 + free_entry(p2); 1.459 + return; 1.460 +} 1.461 + 1.462 + 1.463 +void LoaderConstraintTable::verify(Dictionary* dictionary) { 1.464 + Thread *thread = Thread::current(); 1.465 + for (int cindex = 0; cindex < _loader_constraint_size; cindex++) { 1.466 + for (LoaderConstraintEntry* probe = bucket(cindex); 1.467 + probe != NULL; 1.468 + probe = probe->next()) { 1.469 + guarantee(probe->name()->is_symbol(), "should be symbol"); 1.470 + if (probe->klass() != NULL) { 1.471 + instanceKlass* ik = instanceKlass::cast(probe->klass()); 1.472 + guarantee(ik->name() == probe->name(), "name should match"); 1.473 + symbolHandle name (thread, ik->name()); 1.474 + Handle loader(thread, ik->class_loader()); 1.475 + unsigned int d_hash = dictionary->compute_hash(name, loader); 1.476 + int d_index = dictionary->hash_to_index(d_hash); 1.477 + klassOop k = dictionary->find_class(d_index, d_hash, name, loader); 1.478 + guarantee(k == probe->klass(), "klass should be in dictionary"); 1.479 + } 1.480 + for (int n = 0; n< probe->num_loaders(); n++) { 1.481 + guarantee(probe->loader(n)->is_oop_or_null(), "should be oop"); 1.482 + } 1.483 + } 1.484 + } 1.485 +} 1.486 + 1.487 +#ifndef PRODUCT 1.488 + 1.489 +// Called with the system dictionary lock held 1.490 +void LoaderConstraintTable::print() { 1.491 + ResourceMark rm; 1.492 + 1.493 + assert_locked_or_safepoint(SystemDictionary_lock); 1.494 + tty->print_cr("Java loader constraints (entries=%d)", _loader_constraint_size); 1.495 + for (int cindex = 0; cindex < _loader_constraint_size; cindex++) { 1.496 + for (LoaderConstraintEntry* probe = bucket(cindex); 1.497 + probe != NULL; 1.498 + probe = probe->next()) { 1.499 + tty->print("%4d: ", cindex); 1.500 + probe->name()->print(); 1.501 + tty->print(" , loaders:"); 1.502 + for (int n = 0; n < probe->num_loaders(); n++) { 1.503 + probe->loader(n)->print_value(); 1.504 + tty->print(", "); 1.505 + } 1.506 + tty->cr(); 1.507 + } 1.508 + } 1.509 +} 1.510 +#endif