src/share/vm/classfile/loaderConstraints.cpp

Tue, 23 Nov 2010 13:22:55 -0800

author
stefank
date
Tue, 23 Nov 2010 13:22:55 -0800
changeset 2314
f95d63e2154a
parent 1907
c18cbe5936b8
child 2497
3582bf76420e
permissions
-rw-r--r--

6989984: Use standard include model for Hospot
Summary: Replaced MakeDeps and the includeDB files with more standardized solutions.
Reviewed-by: coleenp, kvn, kamg

     1 /*
     2  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    20  * or visit www.oracle.com if you need additional information or have any
    21  * questions.
    22  *
    23  */
    25 #include "precompiled.hpp"
    26 #include "classfile/loaderConstraints.hpp"
    27 #include "memory/resourceArea.hpp"
    28 #include "oops/oop.inline.hpp"
    29 #include "runtime/handles.inline.hpp"
    30 #include "runtime/safepoint.hpp"
    31 #include "utilities/hashtable.inline.hpp"
    33 LoaderConstraintTable::LoaderConstraintTable(int nof_buckets)
    34   : Hashtable(nof_buckets, sizeof(LoaderConstraintEntry)) {};
    37 LoaderConstraintEntry* LoaderConstraintTable::new_entry(
    38                                  unsigned int hash, symbolOop name,
    39                                  klassOop klass, int num_loaders,
    40                                  int max_loaders) {
    41   LoaderConstraintEntry* entry;
    42   entry = (LoaderConstraintEntry*)Hashtable::new_entry(hash, klass);
    43   entry->set_name(name);
    44   entry->set_num_loaders(num_loaders);
    45   entry->set_max_loaders(max_loaders);
    46   return entry;
    47 }
    50 void LoaderConstraintTable::oops_do(OopClosure* f) {
    51   for (int index = 0; index < table_size(); index++) {
    52     for (LoaderConstraintEntry* probe = bucket(index);
    53                                 probe != NULL;
    54                                 probe = probe->next()) {
    55       f->do_oop((oop*)(probe->name_addr()));
    56       if (probe->klass() != NULL) {
    57         f->do_oop((oop*)probe->klass_addr());
    58       }
    59       for (int n = 0; n < probe->num_loaders(); n++) {
    60         if (probe->loader(n) != NULL) {
    61           f->do_oop(probe->loader_addr(n));
    62         }
    63       }
    64     }
    65   }
    66 }
    68 // We must keep the symbolOop used in the name alive.  We'll use the
    69 // loaders to decide if a particular entry can be purged.
    70 void LoaderConstraintTable::always_strong_classes_do(OopClosure* blk) {
    71   // We must keep the symbolOop used in the name alive.
    72   for (int cindex = 0; cindex < table_size(); cindex++) {
    73     for (LoaderConstraintEntry* lc_probe = bucket(cindex);
    74                                 lc_probe != NULL;
    75                                 lc_probe = lc_probe->next()) {
    76       assert (lc_probe->name() != NULL,  "corrupted loader constraint table");
    77       blk->do_oop((oop*)lc_probe->name_addr());
    78     }
    79   }
    80 }
    83 // The loaderConstraintTable must always be accessed with the
    84 // SystemDictionary lock held. This is true even for readers as
    85 // entries in the table could be being dynamically resized.
    87 LoaderConstraintEntry** LoaderConstraintTable::find_loader_constraint(
    88                                     symbolHandle name, Handle loader) {
    90   unsigned int hash = compute_hash(name);
    91   int index = hash_to_index(hash);
    92   LoaderConstraintEntry** pp = bucket_addr(index);
    93   while (*pp) {
    94     LoaderConstraintEntry* p = *pp;
    95     if (p->hash() == hash) {
    96       if (p->name() == name()) {
    97         for (int i = p->num_loaders() - 1; i >= 0; i--) {
    98           if (p->loader(i) == loader()) {
    99             return pp;
   100           }
   101         }
   102       }
   103     }
   104     pp = p->next_addr();
   105   }
   106   return pp;
   107 }
   110 void LoaderConstraintTable::purge_loader_constraints(BoolObjectClosure* is_alive) {
   111   assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
   112   // Remove unloaded entries from constraint table
   113   for (int index = 0; index < table_size(); index++) {
   114     LoaderConstraintEntry** p = bucket_addr(index);
   115     while(*p) {
   116       LoaderConstraintEntry* probe = *p;
   117       klassOop klass = probe->klass();
   118       // Remove klass that is no longer alive
   119       if (klass != NULL && !is_alive->do_object_b(klass)) {
   120         probe->set_klass(NULL);
   121         if (TraceLoaderConstraints) {
   122           ResourceMark rm;
   123           tty->print_cr("[Purging class object from constraint for name %s,"
   124                      " loader list:",
   125                      probe->name()->as_C_string());
   126           for (int i = 0; i < probe->num_loaders(); i++) {
   127             tty->print_cr("[   [%d]: %s", i,
   128                           SystemDictionary::loader_name(probe->loader(i)));
   129           }
   130         }
   131       }
   132       // Remove entries no longer alive from loader array
   133       int n = 0;
   134       while (n < probe->num_loaders()) {
   135         if (probe->loader(n) != NULL) {
   136           if (!is_alive->do_object_b(probe->loader(n))) {
   137             if (TraceLoaderConstraints) {
   138               ResourceMark rm;
   139               tty->print_cr("[Purging loader %s from constraint for name %s",
   140                             SystemDictionary::loader_name(probe->loader(n)),
   141                             probe->name()->as_C_string()
   142                             );
   143             }
   145             // Compact array
   146             int num = probe->num_loaders() - 1;
   147             probe->set_num_loaders(num);
   148             probe->set_loader(n, probe->loader(num));
   149             probe->set_loader(num, NULL);
   151             if (TraceLoaderConstraints) {
   152               ResourceMark rm;
   153               tty->print_cr("[New loader list:");
   154               for (int i = 0; i < probe->num_loaders(); i++) {
   155                 tty->print_cr("[   [%d]: %s", i,
   156                               SystemDictionary::loader_name(probe->loader(i)));
   157               }
   158             }
   160             continue;  // current element replaced, so restart without
   161                        // incrementing n
   162           }
   163         }
   164         n++;
   165       }
   166       // Check whether entry should be purged
   167       if (probe->num_loaders() < 2) {
   168             if (TraceLoaderConstraints) {
   169               ResourceMark rm;
   170               tty->print("[Purging complete constraint for name %s\n",
   171                          probe->name()->as_C_string());
   172             }
   174         // Purge entry
   175         *p = probe->next();
   176         FREE_C_HEAP_ARRAY(oop, probe->loaders());
   177         free_entry(probe);
   178       } else {
   179 #ifdef ASSERT
   180         assert(is_alive->do_object_b(probe->name()), "name should be live");
   181         if (probe->klass() != NULL) {
   182           assert(is_alive->do_object_b(probe->klass()), "klass should be live");
   183         }
   184         for (n = 0; n < probe->num_loaders(); n++) {
   185           if (probe->loader(n) != NULL) {
   186             assert(is_alive->do_object_b(probe->loader(n)), "loader should be live");
   187           }
   188         }
   189 #endif
   190         // Go to next entry
   191         p = probe->next_addr();
   192       }
   193     }
   194   }
   195 }
   197 bool LoaderConstraintTable::add_entry(symbolHandle class_name,
   198                                       klassOop klass1, Handle class_loader1,
   199                                       klassOop klass2, Handle class_loader2) {
   200   int failure_code = 0; // encode different reasons for failing
   202   if (klass1 != NULL && klass2 != NULL && klass1 != klass2) {
   203     failure_code = 1;
   204   } else {
   205     klassOop klass = klass1 != NULL ? klass1 : klass2;
   207     LoaderConstraintEntry** pp1 = find_loader_constraint(class_name,
   208                                                          class_loader1);
   209     if (*pp1 != NULL && (*pp1)->klass() != NULL) {
   210       if (klass != NULL) {
   211         if (klass != (*pp1)->klass()) {
   212           failure_code = 2;
   213         }
   214       } else {
   215         klass = (*pp1)->klass();
   216       }
   217     }
   219     LoaderConstraintEntry** pp2 = find_loader_constraint(class_name,
   220                                                          class_loader2);
   221     if (*pp2 != NULL && (*pp2)->klass() != NULL) {
   222       if (klass != NULL) {
   223         if (klass != (*pp2)->klass()) {
   224           failure_code = 3;
   225         }
   226       } else {
   227         klass = (*pp2)->klass();
   228       }
   229     }
   231     if (failure_code == 0) {
   232       if (*pp1 == NULL && *pp2 == NULL) {
   233         unsigned int hash = compute_hash(class_name);
   234         int index = hash_to_index(hash);
   235         LoaderConstraintEntry* p;
   236         p = new_entry(hash, class_name(), klass, 2, 2);
   237         p->set_loaders(NEW_C_HEAP_ARRAY(oop, 2));
   238         p->set_loader(0, class_loader1());
   239         p->set_loader(1, class_loader2());
   240         p->set_klass(klass);
   241         p->set_next(bucket(index));
   242         set_entry(index, p);
   243         if (TraceLoaderConstraints) {
   244           ResourceMark rm;
   245           tty->print("[Adding new constraint for name: %s, loader[0]: %s,"
   246                      " loader[1]: %s ]\n",
   247                      class_name()->as_C_string(),
   248                      SystemDictionary::loader_name(class_loader1()),
   249                      SystemDictionary::loader_name(class_loader2())
   250                      );
   251         }
   252       } else if (*pp1 == *pp2) {
   253         /* constraint already imposed */
   254         if ((*pp1)->klass() == NULL) {
   255           (*pp1)->set_klass(klass);
   256           if (TraceLoaderConstraints) {
   257             ResourceMark rm;
   258             tty->print("[Setting class object in existing constraint for"
   259                        " name: %s and loader %s ]\n",
   260                        class_name()->as_C_string(),
   261                        SystemDictionary::loader_name(class_loader1())
   262                        );
   263           }
   264         } else {
   265           assert((*pp1)->klass() == klass, "loader constraints corrupted");
   266         }
   267       } else if (*pp1 == NULL) {
   268         extend_loader_constraint(*pp2, class_loader1, klass);
   269       } else if (*pp2 == NULL) {
   270         extend_loader_constraint(*pp1, class_loader2, klass);
   271       } else {
   272         merge_loader_constraints(pp1, pp2, klass);
   273       }
   274     }
   275   }
   277   if (failure_code != 0 && TraceLoaderConstraints) {
   278     ResourceMark rm;
   279     const char* reason = "";
   280     switch(failure_code) {
   281     case 1: reason = "the class objects presented by loader[0] and loader[1]"
   282               " are different"; break;
   283     case 2: reason = "the class object presented by loader[0] does not match"
   284               " the stored class object in the constraint"; break;
   285     case 3: reason = "the class object presented by loader[1] does not match"
   286               " the stored class object in the constraint"; break;
   287     default: reason = "unknown reason code";
   288     }
   289     tty->print("[Failed to add constraint for name: %s, loader[0]: %s,"
   290                " loader[1]: %s, Reason: %s ]\n",
   291                class_name()->as_C_string(),
   292                SystemDictionary::loader_name(class_loader1()),
   293                SystemDictionary::loader_name(class_loader2()),
   294                reason
   295                );
   296   }
   298   return failure_code == 0;
   299 }
   302 // return true if the constraint was updated, false if the constraint is
   303 // violated
   304 bool LoaderConstraintTable::check_or_update(instanceKlassHandle k,
   305                                                    Handle loader,
   306                                                    symbolHandle name) {
   307   LoaderConstraintEntry* p = *(find_loader_constraint(name, loader));
   308   if (p && p->klass() != NULL && p->klass() != k()) {
   309     if (TraceLoaderConstraints) {
   310       ResourceMark rm;
   311       tty->print("[Constraint check failed for name %s, loader %s: "
   312                  "the presented class object differs from that stored ]\n",
   313                  name()->as_C_string(),
   314                  SystemDictionary::loader_name(loader()));
   315     }
   316     return false;
   317   } else {
   318     if (p && p->klass() == NULL) {
   319       p->set_klass(k());
   320       if (TraceLoaderConstraints) {
   321         ResourceMark rm;
   322         tty->print("[Updating constraint for name %s, loader %s, "
   323                    "by setting class object ]\n",
   324                    name()->as_C_string(),
   325                    SystemDictionary::loader_name(loader()));
   326       }
   327     }
   328     return true;
   329   }
   330 }
   332 klassOop LoaderConstraintTable::find_constrained_klass(symbolHandle name,
   333                                                        Handle loader) {
   334   LoaderConstraintEntry *p = *(find_loader_constraint(name, loader));
   335   if (p != NULL && p->klass() != NULL)
   336     return p->klass();
   338   // No constraints, or else no klass loaded yet.
   339   return NULL;
   340 }
   342 void LoaderConstraintTable::ensure_loader_constraint_capacity(
   343                                                      LoaderConstraintEntry *p,
   344                                                     int nfree) {
   345     if (p->max_loaders() - p->num_loaders() < nfree) {
   346         int n = nfree + p->num_loaders();
   347         oop* new_loaders = NEW_C_HEAP_ARRAY(oop, n);
   348         memcpy(new_loaders, p->loaders(), sizeof(oop) * p->num_loaders());
   349         p->set_max_loaders(n);
   350         FREE_C_HEAP_ARRAY(oop, p->loaders());
   351         p->set_loaders(new_loaders);
   352     }
   353 }
   356 void LoaderConstraintTable::extend_loader_constraint(LoaderConstraintEntry* p,
   357                                                      Handle loader,
   358                                                      klassOop klass) {
   359   ensure_loader_constraint_capacity(p, 1);
   360   int num = p->num_loaders();
   361   p->set_loader(num, loader());
   362   p->set_num_loaders(num + 1);
   363   if (TraceLoaderConstraints) {
   364     ResourceMark rm;
   365     tty->print("[Extending constraint for name %s by adding loader[%d]: %s %s",
   366                p->name()->as_C_string(),
   367                num,
   368                SystemDictionary::loader_name(loader()),
   369                (p->klass() == NULL ? " and setting class object ]\n" : " ]\n")
   370                );
   371   }
   372   if (p->klass() == NULL) {
   373     p->set_klass(klass);
   374   } else {
   375     assert(klass == NULL || p->klass() == klass, "constraints corrupted");
   376   }
   377 }
   380 void LoaderConstraintTable::merge_loader_constraints(
   381                                                    LoaderConstraintEntry** pp1,
   382                                                    LoaderConstraintEntry** pp2,
   383                                                    klassOop klass) {
   384   // make sure *pp1 has higher capacity
   385   if ((*pp1)->max_loaders() < (*pp2)->max_loaders()) {
   386     LoaderConstraintEntry** tmp = pp2;
   387     pp2 = pp1;
   388     pp1 = tmp;
   389   }
   391   LoaderConstraintEntry* p1 = *pp1;
   392   LoaderConstraintEntry* p2 = *pp2;
   394   ensure_loader_constraint_capacity(p1, p2->num_loaders());
   396   for (int i = 0; i < p2->num_loaders(); i++) {
   397     int num = p1->num_loaders();
   398     p1->set_loader(num, p2->loader(i));
   399     p1->set_num_loaders(num + 1);
   400   }
   402   if (TraceLoaderConstraints) {
   403     ResourceMark rm;
   404     tty->print_cr("[Merged constraints for name %s, new loader list:",
   405                   p1->name()->as_C_string()
   406                   );
   408     for (int i = 0; i < p1->num_loaders(); i++) {
   409       tty->print_cr("[   [%d]: %s", i,
   410                     SystemDictionary::loader_name(p1->loader(i)));
   411     }
   412     if (p1->klass() == NULL) {
   413       tty->print_cr("[... and setting class object]");
   414     }
   415   }
   417   // p1->klass() will hold NULL if klass, p2->klass(), and old
   418   // p1->klass() are all NULL.  In addition, all three must have
   419   // matching non-NULL values, otherwise either the constraints would
   420   // have been violated, or the constraints had been corrupted (and an
   421   // assertion would fail).
   422   if (p2->klass() != NULL) {
   423     assert(p2->klass() == klass, "constraints corrupted");
   424   }
   425   if (p1->klass() == NULL) {
   426     p1->set_klass(klass);
   427   } else {
   428     assert(p1->klass() == klass, "constraints corrupted");
   429   }
   431   *pp2 = p2->next();
   432   FREE_C_HEAP_ARRAY(oop, p2->loaders());
   433   free_entry(p2);
   434   return;
   435 }
   438 void LoaderConstraintTable::verify(Dictionary* dictionary,
   439                                    PlaceholderTable* placeholders) {
   440   Thread *thread = Thread::current();
   441   for (int cindex = 0; cindex < _loader_constraint_size; cindex++) {
   442     for (LoaderConstraintEntry* probe = bucket(cindex);
   443                                 probe != NULL;
   444                                 probe = probe->next()) {
   445       guarantee(probe->name()->is_symbol(), "should be symbol");
   446       if (probe->klass() != NULL) {
   447         instanceKlass* ik = instanceKlass::cast(probe->klass());
   448         guarantee(ik->name() == probe->name(), "name should match");
   449         symbolHandle name (thread, ik->name());
   450         Handle loader(thread, ik->class_loader());
   451         unsigned int d_hash = dictionary->compute_hash(name, loader);
   452         int d_index = dictionary->hash_to_index(d_hash);
   453         klassOop k = dictionary->find_class(d_index, d_hash, name, loader);
   454         if (k != NULL) {
   455           // We found the class in the system dictionary, so we should
   456           // make sure that the klassOop matches what we already have.
   457           guarantee(k == probe->klass(), "klass should be in dictionary");
   458         } else {
   459           // If we don't find the class in the system dictionary, it
   460           // has to be in the placeholders table.
   461           unsigned int p_hash = placeholders->compute_hash(name, loader);
   462           int p_index = placeholders->hash_to_index(p_hash);
   463           PlaceholderEntry* entry = placeholders->get_entry(p_index, p_hash,
   464                                                             name, loader);
   466           // The instanceKlass might not be on the entry, so the only
   467           // thing we can check here is whether we were successful in
   468           // finding the class in the placeholders table.
   469           guarantee(entry != NULL, "klass should be in the placeholders");
   470         }
   471       }
   472       for (int n = 0; n< probe->num_loaders(); n++) {
   473         guarantee(probe->loader(n)->is_oop_or_null(), "should be oop");
   474       }
   475     }
   476   }
   477 }
   479 #ifndef PRODUCT
   481 // Called with the system dictionary lock held
   482 void LoaderConstraintTable::print() {
   483   ResourceMark rm;
   485   assert_locked_or_safepoint(SystemDictionary_lock);
   486   tty->print_cr("Java loader constraints (entries=%d)", _loader_constraint_size);
   487   for (int cindex = 0; cindex < _loader_constraint_size; cindex++) {
   488     for (LoaderConstraintEntry* probe = bucket(cindex);
   489                                 probe != NULL;
   490                                 probe = probe->next()) {
   491       tty->print("%4d: ", cindex);
   492       probe->name()->print();
   493       tty->print(" , loaders:");
   494       for (int n = 0; n < probe->num_loaders(); n++) {
   495         probe->loader(n)->print_value();
   496         tty->print(", ");
   497       }
   498       tty->cr();
   499     }
   500   }
   501 }
   502 #endif

mercurial