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