src/share/vm/classfile/loaderConstraints.cpp

Tue, 19 Jan 2010 16:03:09 -0500

author
acorn
date
Tue, 19 Jan 2010 16:03:09 -0500
changeset 1771
0c3f888b7636
parent 435
a61af66fc99e
child 1774
09ac706c2623
permissions
-rw-r--r--

6626217: Fixed loader constraint array handling
Summary: Loader constraints track array elements, not arrays themselves.
Reviewed-by: dcubed, kevinw

     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 }
   337 void LoaderConstraintTable::ensure_loader_constraint_capacity(
   338                                                      LoaderConstraintEntry *p,
   339                                                     int nfree) {
   340     if (p->max_loaders() - p->num_loaders() < nfree) {
   341         int n = nfree + p->num_loaders();
   342         oop* new_loaders = NEW_C_HEAP_ARRAY(oop, n);
   343         memcpy(new_loaders, p->loaders(), sizeof(oop) * p->num_loaders());
   344         p->set_max_loaders(n);
   345         FREE_C_HEAP_ARRAY(oop, p->loaders());
   346         p->set_loaders(new_loaders);
   347     }
   348 }
   351 void LoaderConstraintTable::extend_loader_constraint(LoaderConstraintEntry* p,
   352                                                      Handle loader,
   353                                                      klassOop klass) {
   354   ensure_loader_constraint_capacity(p, 1);
   355   int num = p->num_loaders();
   356   p->set_loader(num, loader());
   357   p->set_num_loaders(num + 1);
   358   if (TraceLoaderConstraints) {
   359     ResourceMark rm;
   360     tty->print("[Extending constraint for name %s by adding loader[%d]: %s %s",
   361                p->name()->as_C_string(),
   362                num,
   363                SystemDictionary::loader_name(loader()),
   364                (p->klass() == NULL ? " and setting class object ]\n" : " ]\n")
   365                );
   366   }
   367   if (p->klass() == NULL) {
   368     p->set_klass(klass);
   369   } else {
   370     assert(klass == NULL || p->klass() == klass, "constraints corrupted");
   371   }
   372 }
   375 void LoaderConstraintTable::merge_loader_constraints(
   376                                                    LoaderConstraintEntry** pp1,
   377                                                    LoaderConstraintEntry** pp2,
   378                                                    klassOop klass) {
   379   // make sure *pp1 has higher capacity
   380   if ((*pp1)->max_loaders() < (*pp2)->max_loaders()) {
   381     LoaderConstraintEntry** tmp = pp2;
   382     pp2 = pp1;
   383     pp1 = tmp;
   384   }
   386   LoaderConstraintEntry* p1 = *pp1;
   387   LoaderConstraintEntry* p2 = *pp2;
   389   ensure_loader_constraint_capacity(p1, p2->num_loaders());
   391   for (int i = 0; i < p2->num_loaders(); i++) {
   392     int num = p1->num_loaders();
   393     p1->set_loader(num, p2->loader(i));
   394     p1->set_num_loaders(num + 1);
   395   }
   397   if (TraceLoaderConstraints) {
   398     ResourceMark rm;
   399     tty->print_cr("[Merged constraints for name %s, new loader list:",
   400                   p1->name()->as_C_string()
   401                   );
   403     for (int i = 0; i < p1->num_loaders(); i++) {
   404       tty->print_cr("[   [%d]: %s", i,
   405                     SystemDictionary::loader_name(p1->loader(i)));
   406     }
   407     if (p1->klass() == NULL) {
   408       tty->print_cr("[... and setting class object]");
   409     }
   410   }
   412   // p1->klass() will hold NULL if klass, p2->klass(), and old
   413   // p1->klass() are all NULL.  In addition, all three must have
   414   // matching non-NULL values, otherwise either the constraints would
   415   // have been violated, or the constraints had been corrupted (and an
   416   // assertion would fail).
   417   if (p2->klass() != NULL) {
   418     assert(p2->klass() == klass, "constraints corrupted");
   419   }
   420   if (p1->klass() == NULL) {
   421     p1->set_klass(klass);
   422   } else {
   423     assert(p1->klass() == klass, "constraints corrupted");
   424   }
   426   *pp2 = p2->next();
   427   FREE_C_HEAP_ARRAY(oop, p2->loaders());
   428   free_entry(p2);
   429   return;
   430 }
   433 void LoaderConstraintTable::verify(Dictionary* dictionary) {
   434   Thread *thread = Thread::current();
   435   for (int cindex = 0; cindex < _loader_constraint_size; cindex++) {
   436     for (LoaderConstraintEntry* probe = bucket(cindex);
   437                                 probe != NULL;
   438                                 probe = probe->next()) {
   439       guarantee(probe->name()->is_symbol(), "should be symbol");
   440       if (probe->klass() != NULL) {
   441         instanceKlass* ik = instanceKlass::cast(probe->klass());
   442         guarantee(ik->name() == probe->name(), "name should match");
   443         symbolHandle name (thread, ik->name());
   444         Handle loader(thread, ik->class_loader());
   445         unsigned int d_hash = dictionary->compute_hash(name, loader);
   446         int d_index = dictionary->hash_to_index(d_hash);
   447         klassOop k = dictionary->find_class(d_index, d_hash, name, loader);
   448         guarantee(k == probe->klass(), "klass should be in dictionary");
   449       }
   450       for (int n = 0; n< probe->num_loaders(); n++) {
   451         guarantee(probe->loader(n)->is_oop_or_null(), "should be oop");
   452       }
   453     }
   454   }
   455 }
   457 #ifndef PRODUCT
   459 // Called with the system dictionary lock held
   460 void LoaderConstraintTable::print() {
   461   ResourceMark rm;
   463   assert_locked_or_safepoint(SystemDictionary_lock);
   464   tty->print_cr("Java loader constraints (entries=%d)", _loader_constraint_size);
   465   for (int cindex = 0; cindex < _loader_constraint_size; cindex++) {
   466     for (LoaderConstraintEntry* probe = bucket(cindex);
   467                                 probe != NULL;
   468                                 probe = probe->next()) {
   469       tty->print("%4d: ", cindex);
   470       probe->name()->print();
   471       tty->print(" , loaders:");
   472       for (int n = 0; n < probe->num_loaders(); n++) {
   473         probe->loader(n)->print_value();
   474         tty->print(", ");
   475       }
   476       tty->cr();
   477     }
   478   }
   479 }
   480 #endif

mercurial