src/share/vm/classfile/loaderConstraints.cpp

Tue, 22 Mar 2011 13:36:33 -0700

author
jcoomes
date
Tue, 22 Mar 2011 13:36:33 -0700
changeset 2661
b099aaf51bf8
parent 2551
4f26f535a225
child 2708
1d1603768966
permissions
-rw-r--r--

6962931: move interned strings out of the perm gen
Reviewed-by: never, coleenp, ysr, jwilhelm

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

mercurial