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