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