src/share/vm/classfile/loaderConstraints.cpp

Sat, 01 Dec 2007 00:00:00 +0000

author
duke
date
Sat, 01 Dec 2007 00:00:00 +0000
changeset 435
a61af66fc99e
child 1693
38836cf1d8d2
child 1771
0c3f888b7636
permissions
-rw-r--r--

Initial load

     1 /*
     2  * Copyright 2003-2006 Sun Microsystems, Inc.  All Rights Reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     8  *
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    12  * version 2 for more details (a copy is included in the LICENSE file that
    13  * accompanied this code).
    14  *
    15  * You should have received a copy of the GNU General Public License version
    16  * 2 along with this work; if not, write to the Free Software Foundation,
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    18  *
    19  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    20  * CA 95054 USA or visit www.sun.com if you need additional information or
    21  * have any questions.
    22  *
    23  */
    25 # include "incls/_precompiled.incl"
    26 # include "incls/_loaderConstraints.cpp.incl"
    28 LoaderConstraintTable::LoaderConstraintTable(int nof_buckets)
    29   : Hashtable(nof_buckets, sizeof(LoaderConstraintEntry)) {};
    32 LoaderConstraintEntry* LoaderConstraintTable::new_entry(
    33                                  unsigned int hash, symbolOop name,
    34                                  klassOop klass, int num_loaders,
    35                                  int max_loaders) {
    36   LoaderConstraintEntry* entry;
    37   entry = (LoaderConstraintEntry*)Hashtable::new_entry(hash, klass);
    38   entry->set_name(name);
    39   entry->set_num_loaders(num_loaders);
    40   entry->set_max_loaders(max_loaders);
    41   return entry;
    42 }
    45 void LoaderConstraintTable::oops_do(OopClosure* f) {
    46   for (int index = 0; index < table_size(); index++) {
    47     for (LoaderConstraintEntry* probe = bucket(index);
    48                                 probe != NULL;
    49                                 probe = probe->next()) {
    50       f->do_oop((oop*)(probe->name_addr()));
    51       if (probe->klass() != NULL) {
    52         f->do_oop((oop*)probe->klass_addr());
    53       }
    54       for (int n = 0; n < probe->num_loaders(); n++) {
    55         if (probe->loader(n) != NULL) {
    56           f->do_oop(probe->loader_addr(n));
    57         }
    58       }
    59     }
    60   }
    61 }
    63 // We must keep the symbolOop used in the name alive.  We'll use the
    64 // loaders to decide if a particular entry can be purged.
    65 void LoaderConstraintTable::always_strong_classes_do(OopClosure* blk) {
    66   // We must keep the symbolOop used in the name alive.
    67   for (int cindex = 0; cindex < table_size(); cindex++) {
    68     for (LoaderConstraintEntry* lc_probe = bucket(cindex);
    69                                 lc_probe != NULL;
    70                                 lc_probe = lc_probe->next()) {
    71       assert (lc_probe->name() != NULL,  "corrupted loader constraint table");
    72       blk->do_oop((oop*)lc_probe->name_addr());
    73     }
    74   }
    75 }
    78 // The loaderConstraintTable must always be accessed with the
    79 // SystemDictionary lock held. This is true even for readers as
    80 // entries in the table could be being dynamically resized.
    82 LoaderConstraintEntry** LoaderConstraintTable::find_loader_constraint(
    83                                     symbolHandle name, Handle loader) {
    85   unsigned int hash = compute_hash(name);
    86   int index = hash_to_index(hash);
    87   LoaderConstraintEntry** pp = bucket_addr(index);
    88   while (*pp) {
    89     LoaderConstraintEntry* p = *pp;
    90     if (p->hash() == hash) {
    91       if (p->name() == name()) {
    92         for (int i = p->num_loaders() - 1; i >= 0; i--) {
    93           if (p->loader(i) == loader()) {
    94             return pp;
    95           }
    96         }
    97       }
    98     }
    99     pp = p->next_addr();
   100   }
   101   return pp;
   102 }
   105 void LoaderConstraintTable::purge_loader_constraints(BoolObjectClosure* is_alive) {
   106   assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint")
   107   // Remove unloaded entries from constraint table
   108   for (int index = 0; index < table_size(); index++) {
   109     LoaderConstraintEntry** p = bucket_addr(index);
   110     while(*p) {
   111       LoaderConstraintEntry* probe = *p;
   112       klassOop klass = probe->klass();
   113       // Remove klass that is no longer alive
   114       if (klass != NULL && !is_alive->do_object_b(klass)) {
   115         probe->set_klass(NULL);
   116         if (TraceLoaderConstraints) {
   117           ResourceMark rm;
   118           tty->print_cr("[Purging class object from constraint for name %s,"
   119                      " loader list:",
   120                      probe->name()->as_C_string());
   121           for (int i = 0; i < probe->num_loaders(); i++) {
   122             tty->print_cr("[   [%d]: %s", i,
   123                           SystemDictionary::loader_name(probe->loader(i)));
   124           }
   125         }
   126       }
   127       // Remove entries no longer alive from loader array
   128       int n = 0;
   129       while (n < probe->num_loaders()) {
   130         if (probe->loader(n) != NULL) {
   131           if (!is_alive->do_object_b(probe->loader(n))) {
   132             if (TraceLoaderConstraints) {
   133               ResourceMark rm;
   134               tty->print_cr("[Purging loader %s from constraint for name %s",
   135                             SystemDictionary::loader_name(probe->loader(n)),
   136                             probe->name()->as_C_string()
   137                             );
   138             }
   140             // Compact array
   141             int num = probe->num_loaders() - 1;
   142             probe->set_num_loaders(num);
   143             probe->set_loader(n, probe->loader(num));
   144             probe->set_loader(num, NULL);
   146             if (TraceLoaderConstraints) {
   147               ResourceMark rm;
   148               tty->print_cr("[New loader list:");
   149               for (int i = 0; i < probe->num_loaders(); i++) {
   150                 tty->print_cr("[   [%d]: %s", i,
   151                               SystemDictionary::loader_name(probe->loader(i)));
   152               }
   153             }
   155             continue;  // current element replaced, so restart without
   156                        // incrementing n
   157           }
   158         }
   159         n++;
   160       }
   161       // Check whether entry should be purged
   162       if (probe->num_loaders() < 2) {
   163             if (TraceLoaderConstraints) {
   164               ResourceMark rm;
   165               tty->print("[Purging complete constraint for name %s\n",
   166                          probe->name()->as_C_string());
   167             }
   169         // Purge entry
   170         *p = probe->next();
   171         FREE_C_HEAP_ARRAY(oop, probe->loaders());
   172         free_entry(probe);
   173       } else {
   174 #ifdef ASSERT
   175         assert(is_alive->do_object_b(probe->name()), "name should be live");
   176         if (probe->klass() != NULL) {
   177           assert(is_alive->do_object_b(probe->klass()), "klass should be live");
   178         }
   179         for (n = 0; n < probe->num_loaders(); n++) {
   180           if (probe->loader(n) != NULL) {
   181             assert(is_alive->do_object_b(probe->loader(n)), "loader should be live");
   182           }
   183         }
   184 #endif
   185         // Go to next entry
   186         p = probe->next_addr();
   187       }
   188     }
   189   }
   190 }
   192 bool LoaderConstraintTable::add_entry(symbolHandle class_name,
   193                                       klassOop klass1, Handle class_loader1,
   194                                       klassOop klass2, Handle class_loader2) {
   195   int failure_code = 0; // encode different reasons for failing
   197   if (klass1 != NULL && klass2 != NULL && klass1 != klass2) {
   198     failure_code = 1;
   199   } else {
   200     klassOop klass = klass1 != NULL ? klass1 : klass2;
   202     LoaderConstraintEntry** pp1 = find_loader_constraint(class_name,
   203                                                          class_loader1);
   204     if (*pp1 != NULL && (*pp1)->klass() != NULL) {
   205       if (klass != NULL) {
   206         if (klass != (*pp1)->klass()) {
   207           failure_code = 2;
   208         }
   209       } else {
   210         klass = (*pp1)->klass();
   211       }
   212     }
   214     LoaderConstraintEntry** pp2 = find_loader_constraint(class_name,
   215                                                          class_loader2);
   216     if (*pp2 != NULL && (*pp2)->klass() != NULL) {
   217       if (klass != NULL) {
   218         if (klass != (*pp2)->klass()) {
   219           failure_code = 3;
   220         }
   221       } else {
   222         klass = (*pp2)->klass();
   223       }
   224     }
   226     if (failure_code == 0) {
   227       if (*pp1 == NULL && *pp2 == NULL) {
   228         unsigned int hash = compute_hash(class_name);
   229         int index = hash_to_index(hash);
   230         LoaderConstraintEntry* p;
   231         p = new_entry(hash, class_name(), klass, 2, 2);
   232         p->set_loaders(NEW_C_HEAP_ARRAY(oop, 2));
   233         p->set_loader(0, class_loader1());
   234         p->set_loader(1, class_loader2());
   235         p->set_klass(klass);
   236         p->set_next(bucket(index));
   237         set_entry(index, p);
   238         if (TraceLoaderConstraints) {
   239           ResourceMark rm;
   240           tty->print("[Adding new constraint for name: %s, loader[0]: %s,"
   241                      " loader[1]: %s ]\n",
   242                      class_name()->as_C_string(),
   243                      SystemDictionary::loader_name(class_loader1()),
   244                      SystemDictionary::loader_name(class_loader2())
   245                      );
   246         }
   247       } else if (*pp1 == *pp2) {
   248         /* constraint already imposed */
   249         if ((*pp1)->klass() == NULL) {
   250           (*pp1)->set_klass(klass);
   251           if (TraceLoaderConstraints) {
   252             ResourceMark rm;
   253             tty->print("[Setting class object in existing constraint for"
   254                        " name: %s and loader %s ]\n",
   255                        class_name()->as_C_string(),
   256                        SystemDictionary::loader_name(class_loader1())
   257                        );
   258           }
   259         } else {
   260           assert((*pp1)->klass() == klass, "loader constraints corrupted");
   261         }
   262       } else if (*pp1 == NULL) {
   263         extend_loader_constraint(*pp2, class_loader1, klass);
   264       } else if (*pp2 == NULL) {
   265         extend_loader_constraint(*pp1, class_loader2, klass);
   266       } else {
   267         merge_loader_constraints(pp1, pp2, klass);
   268       }
   269     }
   270   }
   272   if (failure_code != 0 && TraceLoaderConstraints) {
   273     ResourceMark rm;
   274     const char* reason = "";
   275     switch(failure_code) {
   276     case 1: reason = "the class objects presented by loader[0] and loader[1]"
   277               " are different"; break;
   278     case 2: reason = "the class object presented by loader[0] does not match"
   279               " the stored class object in the constraint"; break;
   280     case 3: reason = "the class object presented by loader[1] does not match"
   281               " the stored class object in the constraint"; break;
   282     default: reason = "unknown reason code";
   283     }
   284     tty->print("[Failed to add constraint for name: %s, loader[0]: %s,"
   285                " loader[1]: %s, Reason: %s ]\n",
   286                class_name()->as_C_string(),
   287                SystemDictionary::loader_name(class_loader1()),
   288                SystemDictionary::loader_name(class_loader2()),
   289                reason
   290                );
   291   }
   293   return failure_code == 0;
   294 }
   297 // return true if the constraint was updated, false if the constraint is
   298 // violated
   299 bool LoaderConstraintTable::check_or_update(instanceKlassHandle k,
   300                                                    Handle loader,
   301                                                    symbolHandle name) {
   302   LoaderConstraintEntry* p = *(find_loader_constraint(name, loader));
   303   if (p && p->klass() != NULL && p->klass() != k()) {
   304     if (TraceLoaderConstraints) {
   305       ResourceMark rm;
   306       tty->print("[Constraint check failed for name %s, loader %s: "
   307                  "the presented class object differs from that stored ]\n",
   308                  name()->as_C_string(),
   309                  SystemDictionary::loader_name(loader()));
   310     }
   311     return false;
   312   } else {
   313     if (p && p->klass() == NULL) {
   314       p->set_klass(k());
   315       if (TraceLoaderConstraints) {
   316         ResourceMark rm;
   317         tty->print("[Updating constraint for name %s, loader %s, "
   318                    "by setting class object ]\n",
   319                    name()->as_C_string(),
   320                    SystemDictionary::loader_name(loader()));
   321       }
   322     }
   323     return true;
   324   }
   325 }
   327 klassOop LoaderConstraintTable::find_constrained_klass(symbolHandle name,
   328                                                        Handle loader) {
   329   LoaderConstraintEntry *p = *(find_loader_constraint(name, loader));
   330   if (p != NULL && p->klass() != NULL)
   331     return p->klass();
   333   // No constraints, or else no klass loaded yet.
   334   return NULL;
   335 }
   338 klassOop LoaderConstraintTable::find_constrained_elem_klass(symbolHandle name,
   339                                                             symbolHandle elem_name,
   340                                                             Handle loader,
   341                                                             TRAPS) {
   342   LoaderConstraintEntry *p = *(find_loader_constraint(name, loader));
   343   if (p != NULL) {
   344     assert(p->klass() == NULL, "Expecting null array klass");
   346     // The array name has a constraint, but it will not have a class. Check
   347     // each loader for an associated elem
   348     for (int i = 0; i < p->num_loaders(); i++) {
   349       Handle no_protection_domain;
   351       klassOop k = SystemDictionary::find(elem_name, p->loader(i), no_protection_domain, THREAD);
   352       if (k != NULL) {
   353         // Return the first elem klass found.
   354         return k;
   355       }
   356     }
   357   }
   359   // No constraints, or else no klass loaded yet.
   360   return NULL;
   361 }
   364 void LoaderConstraintTable::ensure_loader_constraint_capacity(
   365                                                      LoaderConstraintEntry *p,
   366                                                     int nfree) {
   367     if (p->max_loaders() - p->num_loaders() < nfree) {
   368         int n = nfree + p->num_loaders();
   369         oop* new_loaders = NEW_C_HEAP_ARRAY(oop, n);
   370         memcpy(new_loaders, p->loaders(), sizeof(oop) * p->num_loaders());
   371         p->set_max_loaders(n);
   372         FREE_C_HEAP_ARRAY(oop, p->loaders());
   373         p->set_loaders(new_loaders);
   374     }
   375 }
   378 void LoaderConstraintTable::extend_loader_constraint(LoaderConstraintEntry* p,
   379                                                      Handle loader,
   380                                                      klassOop klass) {
   381   ensure_loader_constraint_capacity(p, 1);
   382   int num = p->num_loaders();
   383   p->set_loader(num, loader());
   384   p->set_num_loaders(num + 1);
   385   if (TraceLoaderConstraints) {
   386     ResourceMark rm;
   387     tty->print("[Extending constraint for name %s by adding loader[%d]: %s %s",
   388                p->name()->as_C_string(),
   389                num,
   390                SystemDictionary::loader_name(loader()),
   391                (p->klass() == NULL ? " and setting class object ]\n" : " ]\n")
   392                );
   393   }
   394   if (p->klass() == NULL) {
   395     p->set_klass(klass);
   396   } else {
   397     assert(klass == NULL || p->klass() == klass, "constraints corrupted");
   398   }
   399 }
   402 void LoaderConstraintTable::merge_loader_constraints(
   403                                                    LoaderConstraintEntry** pp1,
   404                                                    LoaderConstraintEntry** pp2,
   405                                                    klassOop klass) {
   406   // make sure *pp1 has higher capacity
   407   if ((*pp1)->max_loaders() < (*pp2)->max_loaders()) {
   408     LoaderConstraintEntry** tmp = pp2;
   409     pp2 = pp1;
   410     pp1 = tmp;
   411   }
   413   LoaderConstraintEntry* p1 = *pp1;
   414   LoaderConstraintEntry* p2 = *pp2;
   416   ensure_loader_constraint_capacity(p1, p2->num_loaders());
   418   for (int i = 0; i < p2->num_loaders(); i++) {
   419     int num = p1->num_loaders();
   420     p1->set_loader(num, p2->loader(i));
   421     p1->set_num_loaders(num + 1);
   422   }
   424   if (TraceLoaderConstraints) {
   425     ResourceMark rm;
   426     tty->print_cr("[Merged constraints for name %s, new loader list:",
   427                   p1->name()->as_C_string()
   428                   );
   430     for (int i = 0; i < p1->num_loaders(); i++) {
   431       tty->print_cr("[   [%d]: %s", i,
   432                     SystemDictionary::loader_name(p1->loader(i)));
   433     }
   434     if (p1->klass() == NULL) {
   435       tty->print_cr("[... and setting class object]");
   436     }
   437   }
   439   // p1->klass() will hold NULL if klass, p2->klass(), and old
   440   // p1->klass() are all NULL.  In addition, all three must have
   441   // matching non-NULL values, otherwise either the constraints would
   442   // have been violated, or the constraints had been corrupted (and an
   443   // assertion would fail).
   444   if (p2->klass() != NULL) {
   445     assert(p2->klass() == klass, "constraints corrupted");
   446   }
   447   if (p1->klass() == NULL) {
   448     p1->set_klass(klass);
   449   } else {
   450     assert(p1->klass() == klass, "constraints corrupted");
   451   }
   453   *pp2 = p2->next();
   454   FREE_C_HEAP_ARRAY(oop, p2->loaders());
   455   free_entry(p2);
   456   return;
   457 }
   460 void LoaderConstraintTable::verify(Dictionary* dictionary) {
   461   Thread *thread = Thread::current();
   462   for (int cindex = 0; cindex < _loader_constraint_size; cindex++) {
   463     for (LoaderConstraintEntry* probe = bucket(cindex);
   464                                 probe != NULL;
   465                                 probe = probe->next()) {
   466       guarantee(probe->name()->is_symbol(), "should be symbol");
   467       if (probe->klass() != NULL) {
   468         instanceKlass* ik = instanceKlass::cast(probe->klass());
   469         guarantee(ik->name() == probe->name(), "name should match");
   470         symbolHandle name (thread, ik->name());
   471         Handle loader(thread, ik->class_loader());
   472         unsigned int d_hash = dictionary->compute_hash(name, loader);
   473         int d_index = dictionary->hash_to_index(d_hash);
   474         klassOop k = dictionary->find_class(d_index, d_hash, name, loader);
   475         guarantee(k == probe->klass(), "klass should be in dictionary");
   476       }
   477       for (int n = 0; n< probe->num_loaders(); n++) {
   478         guarantee(probe->loader(n)->is_oop_or_null(), "should be oop");
   479       }
   480     }
   481   }
   482 }
   484 #ifndef PRODUCT
   486 // Called with the system dictionary lock held
   487 void LoaderConstraintTable::print() {
   488   ResourceMark rm;
   490   assert_locked_or_safepoint(SystemDictionary_lock);
   491   tty->print_cr("Java loader constraints (entries=%d)", _loader_constraint_size);
   492   for (int cindex = 0; cindex < _loader_constraint_size; cindex++) {
   493     for (LoaderConstraintEntry* probe = bucket(cindex);
   494                                 probe != NULL;
   495                                 probe = probe->next()) {
   496       tty->print("%4d: ", cindex);
   497       probe->name()->print();
   498       tty->print(" , loaders:");
   499       for (int n = 0; n < probe->num_loaders(); n++) {
   500         probe->loader(n)->print_value();
   501         tty->print(", ");
   502       }
   503       tty->cr();
   504     }
   505   }
   506 }
   507 #endif

mercurial