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