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