loaderConstraints.cpp revision 1472:c18cbe5936b8
1/*
2 * Copyright (c) 2003, 2006, 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 "incls/_precompiled.incl"
26# include "incls/_loaderConstraints.cpp.incl"
27
28LoaderConstraintTable::LoaderConstraintTable(int nof_buckets)
29  : Hashtable(nof_buckets, sizeof(LoaderConstraintEntry)) {};
30
31
32LoaderConstraintEntry* 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}
43
44
45void 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}
62
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.
65void 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}
76
77
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.
81
82LoaderConstraintEntry** LoaderConstraintTable::find_loader_constraint(
83                                    symbolHandle name, Handle loader) {
84
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}
103
104
105void 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            }
139
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);
145
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            }
154
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            }
168
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}
191
192bool 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
196
197  if (klass1 != NULL && klass2 != NULL && klass1 != klass2) {
198    failure_code = 1;
199  } else {
200    klassOop klass = klass1 != NULL ? klass1 : klass2;
201
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    }
213
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    }
225
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  }
271
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  }
292
293  return failure_code == 0;
294}
295
296
297// return true if the constraint was updated, false if the constraint is
298// violated
299bool 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}
326
327klassOop 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();
332
333  // No constraints, or else no klass loaded yet.
334  return NULL;
335}
336
337void 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}
349
350
351void 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}
373
374
375void 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  }
385
386  LoaderConstraintEntry* p1 = *pp1;
387  LoaderConstraintEntry* p2 = *pp2;
388
389  ensure_loader_constraint_capacity(p1, p2->num_loaders());
390
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  }
396
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                  );
402
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  }
411
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  }
425
426  *pp2 = p2->next();
427  FREE_C_HEAP_ARRAY(oop, p2->loaders());
428  free_entry(p2);
429  return;
430}
431
432
433void LoaderConstraintTable::verify(Dictionary* dictionary,
434                                   PlaceholderTable* placeholders) {
435  Thread *thread = Thread::current();
436  for (int cindex = 0; cindex < _loader_constraint_size; cindex++) {
437    for (LoaderConstraintEntry* probe = bucket(cindex);
438                                probe != NULL;
439                                probe = probe->next()) {
440      guarantee(probe->name()->is_symbol(), "should be symbol");
441      if (probe->klass() != NULL) {
442        instanceKlass* ik = instanceKlass::cast(probe->klass());
443        guarantee(ik->name() == probe->name(), "name should match");
444        symbolHandle name (thread, 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);
460
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}
473
474#ifndef PRODUCT
475
476// Called with the system dictionary lock held
477void LoaderConstraintTable::print() {
478  ResourceMark rm;
479
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
498