loaderConstraints.cpp revision 1879:f95d63e2154a
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 */
24
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"
32
33LoaderConstraintTable::LoaderConstraintTable(int nof_buckets)
34  : Hashtable(nof_buckets, sizeof(LoaderConstraintEntry)) {};
35
36
37LoaderConstraintEntry* 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}
48
49
50void 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}
67
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.
70void 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}
81
82
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.
86
87LoaderConstraintEntry** LoaderConstraintTable::find_loader_constraint(
88                                    symbolHandle name, Handle loader) {
89
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}
108
109
110void 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            }
144
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);
150
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            }
159
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            }
173
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}
196
197bool 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
201
202  if (klass1 != NULL && klass2 != NULL && klass1 != klass2) {
203    failure_code = 1;
204  } else {
205    klassOop klass = klass1 != NULL ? klass1 : klass2;
206
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    }
218
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    }
230
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  }
276
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  }
297
298  return failure_code == 0;
299}
300
301
302// return true if the constraint was updated, false if the constraint is
303// violated
304bool 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}
331
332klassOop 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();
337
338  // No constraints, or else no klass loaded yet.
339  return NULL;
340}
341
342void 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}
354
355
356void 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}
378
379
380void 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  }
390
391  LoaderConstraintEntry* p1 = *pp1;
392  LoaderConstraintEntry* p2 = *pp2;
393
394  ensure_loader_constraint_capacity(p1, p2->num_loaders());
395
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  }
401
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                  );
407
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  }
416
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  }
430
431  *pp2 = p2->next();
432  FREE_C_HEAP_ARRAY(oop, p2->loaders());
433  free_entry(p2);
434  return;
435}
436
437
438void 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);
465
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}
478
479#ifndef PRODUCT
480
481// Called with the system dictionary lock held
482void LoaderConstraintTable::print() {
483  ResourceMark rm;
484
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
503