Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/hotspot/share/cds/classListParser.cpp
41145 views
1
/*
2
* Copyright (c) 2015, 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 "jvm.h"
27
#include "jimage.hpp"
28
#include "cds/archiveUtils.hpp"
29
#include "cds/classListParser.hpp"
30
#include "cds/lambdaFormInvokers.hpp"
31
#include "cds/metaspaceShared.hpp"
32
#include "classfile/classLoaderExt.hpp"
33
#include "classfile/javaClasses.inline.hpp"
34
#include "classfile/symbolTable.hpp"
35
#include "classfile/systemDictionary.hpp"
36
#include "classfile/systemDictionaryShared.hpp"
37
#include "classfile/vmClasses.hpp"
38
#include "classfile/vmSymbols.hpp"
39
#include "interpreter/bytecode.hpp"
40
#include "interpreter/bytecodeStream.hpp"
41
#include "interpreter/linkResolver.hpp"
42
#include "logging/log.hpp"
43
#include "logging/logTag.hpp"
44
#include "memory/resourceArea.hpp"
45
#include "oops/constantPool.hpp"
46
#include "runtime/atomic.hpp"
47
#include "runtime/handles.inline.hpp"
48
#include "runtime/java.hpp"
49
#include "runtime/javaCalls.hpp"
50
#include "utilities/defaultStream.hpp"
51
#include "utilities/hashtable.inline.hpp"
52
#include "utilities/macros.hpp"
53
54
volatile Thread* ClassListParser::_parsing_thread = NULL;
55
ClassListParser* ClassListParser::_instance = NULL;
56
57
ClassListParser::ClassListParser(const char* file) : _id2klass_table(INITIAL_TABLE_SIZE) {
58
_classlist_file = file;
59
_file = NULL;
60
// Use os::open() because neither fopen() nor os::fopen()
61
// can handle long path name on Windows.
62
int fd = os::open(file, O_RDONLY, S_IREAD);
63
if (fd != -1) {
64
// Obtain a File* from the file descriptor so that fgets()
65
// can be used in parse_one_line()
66
_file = os::open(fd, "r");
67
}
68
if (_file == NULL) {
69
char errmsg[JVM_MAXPATHLEN];
70
os::lasterror(errmsg, JVM_MAXPATHLEN);
71
vm_exit_during_initialization("Loading classlist failed", errmsg);
72
}
73
_line_no = 0;
74
_interfaces = new (ResourceObj::C_HEAP, mtClass) GrowableArray<int>(10, mtClass);
75
_indy_items = new (ResourceObj::C_HEAP, mtClass) GrowableArray<const char*>(9, mtClass);
76
77
// _instance should only be accessed by the thread that created _instance.
78
assert(_instance == NULL, "must be singleton");
79
_instance = this;
80
Atomic::store(&_parsing_thread, Thread::current());
81
}
82
83
bool ClassListParser::is_parsing_thread() {
84
return Atomic::load(&_parsing_thread) == Thread::current();
85
}
86
87
ClassListParser::~ClassListParser() {
88
if (_file) {
89
fclose(_file);
90
}
91
Atomic::store(&_parsing_thread, (Thread*)NULL);
92
_instance = NULL;
93
}
94
95
int ClassListParser::parse(TRAPS) {
96
int class_count = 0;
97
98
while (parse_one_line()) {
99
if (lambda_form_line()) {
100
// The current line is "@lambda-form-invoker ...". It has been recorded in LambdaFormInvokers,
101
// and will be processed later.
102
continue;
103
}
104
105
TempNewSymbol class_name_symbol = SymbolTable::new_symbol(_class_name);
106
if (_indy_items->length() > 0) {
107
// The current line is "@lambda-proxy class_name". Load the proxy class.
108
resolve_indy(THREAD, class_name_symbol);
109
class_count++;
110
continue;
111
}
112
113
Klass* klass = load_current_class(class_name_symbol, THREAD);
114
if (HAS_PENDING_EXCEPTION) {
115
if (PENDING_EXCEPTION->is_a(vmClasses::OutOfMemoryError_klass())) {
116
// If we have run out of memory, don't try to load the rest of the classes in
117
// the classlist. Throw an exception, which will terminate the dumping process.
118
return 0; // THROW
119
}
120
121
// We might have an invalid class name or an bad class. Warn about it
122
// and keep going to the next line.
123
CLEAR_PENDING_EXCEPTION;
124
log_warning(cds)("Preload Warning: Cannot find %s", _class_name);
125
continue;
126
}
127
128
assert(klass != NULL, "sanity");
129
if (log_is_enabled(Trace, cds)) {
130
ResourceMark rm(THREAD);
131
log_trace(cds)("Shared spaces preloaded: %s", klass->external_name());
132
}
133
134
if (klass->is_instance_klass()) {
135
InstanceKlass* ik = InstanceKlass::cast(klass);
136
137
// Link the class to cause the bytecodes to be rewritten and the
138
// cpcache to be created. The linking is done as soon as classes
139
// are loaded in order that the related data structures (klass and
140
// cpCache) are located together.
141
MetaspaceShared::try_link_class(THREAD, ik);
142
}
143
144
class_count++;
145
}
146
147
return class_count;
148
}
149
150
bool ClassListParser::parse_one_line() {
151
for (;;) {
152
if (fgets(_line, sizeof(_line), _file) == NULL) {
153
return false;
154
}
155
++ _line_no;
156
_line_len = (int)strlen(_line);
157
if (_line_len > _max_allowed_line_len) {
158
error("input line too long (must be no longer than %d chars)", _max_allowed_line_len);
159
}
160
if (*_line == '#') { // comment
161
continue;
162
}
163
164
{
165
int len = (int)strlen(_line);
166
int i;
167
// Replace \t\r\n\f with ' '
168
for (i=0; i<len; i++) {
169
if (_line[i] == '\t' || _line[i] == '\r' || _line[i] == '\n' || _line[i] == '\f') {
170
_line[i] = ' ';
171
}
172
}
173
174
// Remove trailing newline/space
175
while (len > 0) {
176
if (_line[len-1] == ' ') {
177
_line[len-1] = '\0';
178
len --;
179
} else {
180
break;
181
}
182
}
183
_line_len = len;
184
}
185
186
// valid line
187
break;
188
}
189
190
_class_name = _line;
191
_id = _unspecified;
192
_super = _unspecified;
193
_interfaces->clear();
194
_source = NULL;
195
_interfaces_specified = false;
196
_indy_items->clear();
197
_lambda_form_line = false;
198
199
if (_line[0] == '@') {
200
return parse_at_tags();
201
}
202
203
if ((_token = strchr(_line, ' ')) == NULL) {
204
// No optional arguments are specified.
205
return true;
206
}
207
208
// Mark the end of the name, and go to the next input char
209
*_token++ = '\0';
210
211
while (*_token) {
212
skip_whitespaces();
213
214
if (parse_uint_option("id:", &_id)) {
215
continue;
216
} else if (parse_uint_option("super:", &_super)) {
217
check_already_loaded("Super class", _super);
218
continue;
219
} else if (skip_token("interfaces:")) {
220
int i;
221
while (try_parse_uint(&i)) {
222
check_already_loaded("Interface", i);
223
_interfaces->append(i);
224
}
225
} else if (skip_token("source:")) {
226
skip_whitespaces();
227
_source = _token;
228
char* s = strchr(_token, ' ');
229
if (s == NULL) {
230
break; // end of input line
231
} else {
232
*s = '\0'; // mark the end of _source
233
_token = s+1;
234
}
235
} else {
236
error("Unknown input");
237
}
238
}
239
240
// if src is specified
241
// id super interfaces must all be specified
242
// loader may be specified
243
// else
244
// # the class is loaded from classpath
245
// id may be specified
246
// super, interfaces, loader must not be specified
247
return true;
248
}
249
250
void ClassListParser::split_tokens_by_whitespace(int offset) {
251
int start = offset;
252
int end;
253
bool done = false;
254
while (!done) {
255
while (_line[start] == ' ' || _line[start] == '\t') start++;
256
end = start;
257
while (_line[end] && _line[end] != ' ' && _line[end] != '\t') end++;
258
if (_line[end] == '\0') {
259
done = true;
260
} else {
261
_line[end] = '\0';
262
}
263
_indy_items->append(_line + start);
264
start = ++end;
265
}
266
}
267
268
int ClassListParser::split_at_tag_from_line() {
269
_token = _line;
270
char* ptr;
271
if ((ptr = strchr(_line, ' ')) == NULL) {
272
error("Too few items following the @ tag \"%s\" line #%d", _line, _line_no);
273
return 0;
274
}
275
*ptr++ = '\0';
276
while (*ptr == ' ' || *ptr == '\t') ptr++;
277
return (int)(ptr - _line);
278
}
279
280
bool ClassListParser::parse_at_tags() {
281
assert(_line[0] == '@', "must be");
282
int offset;
283
if ((offset = split_at_tag_from_line()) == 0) {
284
return false;
285
}
286
287
if (strcmp(_token, LAMBDA_PROXY_TAG) == 0) {
288
split_tokens_by_whitespace(offset);
289
if (_indy_items->length() < 2) {
290
error("Line with @ tag has too few items \"%s\" line #%d", _token, _line_no);
291
return false;
292
}
293
// set the class name
294
_class_name = _indy_items->at(0);
295
return true;
296
} else if (strcmp(_token, LAMBDA_FORM_TAG) == 0) {
297
LambdaFormInvokers::append(os::strdup((const char*)(_line + offset), mtInternal));
298
_lambda_form_line = true;
299
return true;
300
} else {
301
error("Invalid @ tag at the beginning of line \"%s\" line #%d", _token, _line_no);
302
return false;
303
}
304
}
305
306
void ClassListParser::skip_whitespaces() {
307
while (*_token == ' ' || *_token == '\t') {
308
_token ++;
309
}
310
}
311
312
void ClassListParser::skip_non_whitespaces() {
313
while (*_token && *_token != ' ' && *_token != '\t') {
314
_token ++;
315
}
316
}
317
318
void ClassListParser::parse_int(int* value) {
319
skip_whitespaces();
320
if (sscanf(_token, "%i", value) == 1) {
321
skip_non_whitespaces();
322
} else {
323
error("Error: expected integer");
324
}
325
}
326
327
void ClassListParser::parse_uint(int* value) {
328
parse_int(value);
329
if (*value < 0) {
330
error("Error: negative integers not allowed (%d)", *value);
331
}
332
}
333
334
bool ClassListParser::try_parse_uint(int* value) {
335
skip_whitespaces();
336
if (sscanf(_token, "%i", value) == 1) {
337
skip_non_whitespaces();
338
return true;
339
}
340
return false;
341
}
342
343
bool ClassListParser::skip_token(const char* option_name) {
344
size_t len = strlen(option_name);
345
if (strncmp(_token, option_name, len) == 0) {
346
_token += len;
347
return true;
348
} else {
349
return false;
350
}
351
}
352
353
bool ClassListParser::parse_int_option(const char* option_name, int* value) {
354
if (skip_token(option_name)) {
355
if (*value != _unspecified) {
356
error("%s specified twice", option_name);
357
} else {
358
parse_int(value);
359
return true;
360
}
361
}
362
return false;
363
}
364
365
bool ClassListParser::parse_uint_option(const char* option_name, int* value) {
366
if (skip_token(option_name)) {
367
if (*value != _unspecified) {
368
error("%s specified twice", option_name);
369
} else {
370
parse_uint(value);
371
return true;
372
}
373
}
374
return false;
375
}
376
377
void ClassListParser::print_specified_interfaces() {
378
const int n = _interfaces->length();
379
jio_fprintf(defaultStream::error_stream(), "Currently specified interfaces[%d] = {\n", n);
380
for (int i=0; i<n; i++) {
381
InstanceKlass* k = lookup_class_by_id(_interfaces->at(i));
382
jio_fprintf(defaultStream::error_stream(), " %4d = %s\n", _interfaces->at(i), k->name()->as_klass_external_name());
383
}
384
jio_fprintf(defaultStream::error_stream(), "}\n");
385
}
386
387
void ClassListParser::print_actual_interfaces(InstanceKlass* ik) {
388
int n = ik->local_interfaces()->length();
389
jio_fprintf(defaultStream::error_stream(), "Actual interfaces[%d] = {\n", n);
390
for (int i = 0; i < n; i++) {
391
InstanceKlass* e = ik->local_interfaces()->at(i);
392
jio_fprintf(defaultStream::error_stream(), " %s\n", e->name()->as_klass_external_name());
393
}
394
jio_fprintf(defaultStream::error_stream(), "}\n");
395
}
396
397
void ClassListParser::error(const char* msg, ...) {
398
va_list ap;
399
va_start(ap, msg);
400
int error_index = _token - _line;
401
if (error_index >= _line_len) {
402
error_index = _line_len - 1;
403
}
404
if (error_index < 0) {
405
error_index = 0;
406
}
407
408
jio_fprintf(defaultStream::error_stream(),
409
"An error has occurred while processing class list file %s %d:%d.\n",
410
_classlist_file, _line_no, (error_index + 1));
411
jio_vfprintf(defaultStream::error_stream(), msg, ap);
412
413
if (_line_len <= 0) {
414
jio_fprintf(defaultStream::error_stream(), "\n");
415
} else {
416
jio_fprintf(defaultStream::error_stream(), ":\n");
417
for (int i=0; i<_line_len; i++) {
418
char c = _line[i];
419
if (c == '\0') {
420
jio_fprintf(defaultStream::error_stream(), "%s", " ");
421
} else {
422
jio_fprintf(defaultStream::error_stream(), "%c", c);
423
}
424
}
425
jio_fprintf(defaultStream::error_stream(), "\n");
426
for (int i=0; i<error_index; i++) {
427
jio_fprintf(defaultStream::error_stream(), "%s", " ");
428
}
429
jio_fprintf(defaultStream::error_stream(), "^\n");
430
}
431
432
vm_exit_during_initialization("class list format error.", NULL);
433
va_end(ap);
434
}
435
436
// This function is used for loading classes for customized class loaders
437
// during archive dumping.
438
InstanceKlass* ClassListParser::load_class_from_source(Symbol* class_name, TRAPS) {
439
#if !(defined(_LP64) && (defined(LINUX) || defined(__APPLE__)))
440
// The only supported platforms are: (1) Linux/64-bit and (2) Solaris/64-bit and
441
// (3) MacOSX/64-bit
442
// This #if condition should be in sync with the areCustomLoadersSupportedForCDS
443
// method in test/lib/jdk/test/lib/Platform.java.
444
error("AppCDS custom class loaders not supported on this platform");
445
#endif
446
447
if (!is_super_specified()) {
448
error("If source location is specified, super class must be also specified");
449
}
450
if (!is_id_specified()) {
451
error("If source location is specified, id must be also specified");
452
}
453
if (strncmp(_class_name, "java/", 5) == 0) {
454
log_info(cds)("Prohibited package for non-bootstrap classes: %s.class from %s",
455
_class_name, _source);
456
THROW_NULL(vmSymbols::java_lang_ClassNotFoundException());
457
}
458
459
InstanceKlass* k = ClassLoaderExt::load_class(class_name, _source, CHECK_NULL);
460
if (k->local_interfaces()->length() != _interfaces->length()) {
461
print_specified_interfaces();
462
print_actual_interfaces(k);
463
error("The number of interfaces (%d) specified in class list does not match the class file (%d)",
464
_interfaces->length(), k->local_interfaces()->length());
465
}
466
467
bool added = SystemDictionaryShared::add_unregistered_class(THREAD, k);
468
if (!added) {
469
// We allow only a single unregistered class for each unique name.
470
error("Duplicated class %s", _class_name);
471
}
472
473
// This tells JVM_FindLoadedClass to not find this class.
474
k->set_shared_classpath_index(UNREGISTERED_INDEX);
475
k->clear_shared_class_loader_type();
476
477
return k;
478
}
479
480
void ClassListParser::populate_cds_indy_info(const constantPoolHandle &pool, int cp_index, CDSIndyInfo* cii, TRAPS) {
481
// Caller needs to allocate ResourceMark.
482
int type_index = pool->bootstrap_name_and_type_ref_index_at(cp_index);
483
int name_index = pool->name_ref_index_at(type_index);
484
cii->add_item(pool->symbol_at(name_index)->as_C_string());
485
int sig_index = pool->signature_ref_index_at(type_index);
486
cii->add_item(pool->symbol_at(sig_index)->as_C_string());
487
int argc = pool->bootstrap_argument_count_at(cp_index);
488
if (argc > 0) {
489
for (int arg_i = 0; arg_i < argc; arg_i++) {
490
int arg = pool->bootstrap_argument_index_at(cp_index, arg_i);
491
jbyte tag = pool->tag_at(arg).value();
492
if (tag == JVM_CONSTANT_MethodType) {
493
cii->add_item(pool->method_type_signature_at(arg)->as_C_string());
494
} else if (tag == JVM_CONSTANT_MethodHandle) {
495
cii->add_ref_kind(pool->method_handle_ref_kind_at(arg));
496
int callee_index = pool->method_handle_klass_index_at(arg);
497
Klass* callee = pool->klass_at(callee_index, CHECK);
498
cii->add_item(callee->name()->as_C_string());
499
cii->add_item(pool->method_handle_name_ref_at(arg)->as_C_string());
500
cii->add_item(pool->method_handle_signature_ref_at(arg)->as_C_string());
501
} else {
502
ShouldNotReachHere();
503
}
504
}
505
}
506
}
507
508
bool ClassListParser::is_matching_cp_entry(constantPoolHandle &pool, int cp_index, TRAPS) {
509
ResourceMark rm(THREAD);
510
CDSIndyInfo cii;
511
populate_cds_indy_info(pool, cp_index, &cii, CHECK_0);
512
GrowableArray<const char*>* items = cii.items();
513
int indy_info_offset = 1;
514
if (_indy_items->length() - indy_info_offset != items->length()) {
515
return false;
516
}
517
for (int i = 0; i < items->length(); i++) {
518
if (strcmp(_indy_items->at(i + indy_info_offset), items->at(i)) != 0) {
519
return false;
520
}
521
}
522
return true;
523
}
524
525
void ClassListParser::resolve_indy(JavaThread* current, Symbol* class_name_symbol) {
526
ExceptionMark em(current);
527
JavaThread* THREAD = current; // For exception macros.
528
ClassListParser::resolve_indy_impl(class_name_symbol, THREAD);
529
if (HAS_PENDING_EXCEPTION) {
530
ResourceMark rm(current);
531
char* ex_msg = (char*)"";
532
oop message = java_lang_Throwable::message(PENDING_EXCEPTION);
533
if (message != NULL) {
534
ex_msg = java_lang_String::as_utf8_string(message);
535
}
536
log_warning(cds)("resolve_indy for class %s has encountered exception: %s %s",
537
class_name_symbol->as_C_string(),
538
PENDING_EXCEPTION->klass()->external_name(),
539
ex_msg);
540
CLEAR_PENDING_EXCEPTION;
541
}
542
}
543
544
void ClassListParser::resolve_indy_impl(Symbol* class_name_symbol, TRAPS) {
545
Handle class_loader(THREAD, SystemDictionary::java_system_loader());
546
Handle protection_domain;
547
Klass* klass = SystemDictionary::resolve_or_fail(class_name_symbol, class_loader, protection_domain, true, CHECK);
548
if (klass->is_instance_klass()) {
549
InstanceKlass* ik = InstanceKlass::cast(klass);
550
MetaspaceShared::try_link_class(THREAD, ik);
551
if (!ik->is_linked()) {
552
// Verification of ik has failed
553
return;
554
}
555
556
ConstantPool* cp = ik->constants();
557
ConstantPoolCache* cpcache = cp->cache();
558
bool found = false;
559
for (int cpcindex = 0; cpcindex < cpcache->length(); cpcindex ++) {
560
int indy_index = ConstantPool::encode_invokedynamic_index(cpcindex);
561
ConstantPoolCacheEntry* cpce = cpcache->entry_at(cpcindex);
562
int pool_index = cpce->constant_pool_index();
563
constantPoolHandle pool(THREAD, cp);
564
if (pool->tag_at(pool_index).is_invoke_dynamic()) {
565
BootstrapInfo bootstrap_specifier(pool, pool_index, indy_index);
566
Handle bsm = bootstrap_specifier.resolve_bsm(CHECK);
567
if (!SystemDictionaryShared::is_supported_invokedynamic(&bootstrap_specifier)) {
568
log_debug(cds, lambda)("is_supported_invokedynamic check failed for cp_index %d", pool_index);
569
continue;
570
}
571
bool matched = is_matching_cp_entry(pool, pool_index, CHECK);
572
if (matched) {
573
found = true;
574
CallInfo info;
575
bool is_done = bootstrap_specifier.resolve_previously_linked_invokedynamic(info, CHECK);
576
if (!is_done) {
577
// resolve it
578
Handle recv;
579
LinkResolver::resolve_invoke(info, recv, pool, indy_index, Bytecodes::_invokedynamic, CHECK);
580
break;
581
}
582
cpce->set_dynamic_call(pool, info);
583
}
584
}
585
}
586
if (!found) {
587
ResourceMark rm(THREAD);
588
log_warning(cds)("No invoke dynamic constant pool entry can be found for class %s. The classlist is probably out-of-date.",
589
class_name_symbol->as_C_string());
590
}
591
}
592
}
593
594
Klass* ClassListParser::load_current_class(Symbol* class_name_symbol, TRAPS) {
595
Klass* klass;
596
if (!is_loading_from_source()) {
597
// Load classes for the boot/platform/app loaders only.
598
if (is_super_specified()) {
599
error("If source location is not specified, super class must not be specified");
600
}
601
if (are_interfaces_specified()) {
602
error("If source location is not specified, interface(s) must not be specified");
603
}
604
605
if (Signature::is_array(class_name_symbol)) {
606
// array classes are not supported in class list.
607
THROW_NULL(vmSymbols::java_lang_ClassNotFoundException());
608
}
609
610
JavaValue result(T_OBJECT);
611
// Call java_system_loader().loadClass() directly, which will
612
// delegate to the correct loader (boot, platform or app) depending on
613
// the package name.
614
615
Handle s = java_lang_String::create_from_symbol(class_name_symbol, CHECK_NULL);
616
// ClassLoader.loadClass() wants external class name format, i.e., convert '/' chars to '.'
617
Handle ext_class_name = java_lang_String::externalize_classname(s, CHECK_NULL);
618
Handle loader = Handle(THREAD, SystemDictionary::java_system_loader());
619
620
JavaCalls::call_virtual(&result,
621
loader, //SystemDictionary::java_system_loader(),
622
vmClasses::ClassLoader_klass(),
623
vmSymbols::loadClass_name(),
624
vmSymbols::string_class_signature(),
625
ext_class_name,
626
CHECK_NULL);
627
628
assert(result.get_type() == T_OBJECT, "just checking");
629
oop obj = result.get_oop();
630
assert(obj != NULL, "jdk.internal.loader.BuiltinClassLoader::loadClass never returns null");
631
klass = java_lang_Class::as_Klass(obj);
632
} else {
633
// If "source:" tag is specified, all super class and super interfaces must be specified in the
634
// class list file.
635
klass = load_class_from_source(class_name_symbol, CHECK_NULL);
636
}
637
638
assert(klass != NULL, "exception should have been thrown");
639
assert(klass->is_instance_klass(), "array classes should have been filtered out");
640
641
if (is_id_specified()) {
642
InstanceKlass* ik = InstanceKlass::cast(klass);
643
int id = this->id();
644
SystemDictionaryShared::update_shared_entry(ik, id);
645
InstanceKlass** old_ptr = table()->lookup(id);
646
if (old_ptr != NULL) {
647
error("Duplicated ID %d for class %s", id, _class_name);
648
}
649
table()->add(id, ik);
650
}
651
652
return klass;
653
}
654
655
bool ClassListParser::is_loading_from_source() {
656
return (_source != NULL);
657
}
658
659
InstanceKlass* ClassListParser::lookup_class_by_id(int id) {
660
InstanceKlass** klass_ptr = table()->lookup(id);
661
if (klass_ptr == NULL) {
662
error("Class ID %d has not been defined", id);
663
}
664
assert(*klass_ptr != NULL, "must be");
665
return *klass_ptr;
666
}
667
668
669
InstanceKlass* ClassListParser::lookup_super_for_current_class(Symbol* super_name) {
670
if (!is_loading_from_source()) {
671
return NULL;
672
}
673
674
InstanceKlass* k = lookup_class_by_id(super());
675
if (super_name != k->name()) {
676
error("The specified super class %s (id %d) does not match actual super class %s",
677
k->name()->as_klass_external_name(), super(),
678
super_name->as_klass_external_name());
679
}
680
return k;
681
}
682
683
InstanceKlass* ClassListParser::lookup_interface_for_current_class(Symbol* interface_name) {
684
if (!is_loading_from_source()) {
685
return NULL;
686
}
687
688
const int n = _interfaces->length();
689
if (n == 0) {
690
error("Class %s implements the interface %s, but no interface has been specified in the input line",
691
_class_name, interface_name->as_klass_external_name());
692
ShouldNotReachHere();
693
}
694
695
int i;
696
for (i=0; i<n; i++) {
697
InstanceKlass* k = lookup_class_by_id(_interfaces->at(i));
698
if (interface_name == k->name()) {
699
return k;
700
}
701
}
702
703
// interface_name is not specified by the "interfaces:" keyword.
704
print_specified_interfaces();
705
error("The interface %s implemented by class %s does not match any of the specified interface IDs",
706
interface_name->as_klass_external_name(), _class_name);
707
ShouldNotReachHere();
708
return NULL;
709
}
710
711