1 /* 2 * Copyright (c) 2015, 2025, 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 "cds/aotConstantPoolResolver.hpp" 26 #include "cds/aotLogging.hpp" 27 #include "cds/archiveUtils.hpp" 28 #include "cds/cdsConfig.hpp" 29 #include "cds/classListParser.hpp" 30 #include "cds/lambdaFormInvokers.hpp" 31 #include "cds/lambdaProxyClassDictionary.hpp" 32 #include "cds/metaspaceShared.hpp" 33 #include "cds/unregisteredClasses.hpp" 34 #include "classfile/classLoader.hpp" 35 #include "classfile/javaClasses.inline.hpp" 36 #include "classfile/symbolTable.hpp" 37 #include "classfile/systemDictionary.hpp" 38 #include "classfile/systemDictionaryShared.hpp" 39 #include "classfile/vmClasses.hpp" 40 #include "classfile/vmSymbols.hpp" 41 #include "interpreter/bytecode.hpp" 42 #include "interpreter/interpreterRuntime.hpp" 43 #include "interpreter/linkResolver.hpp" 44 #include "jimage.hpp" 45 #include "jvm.h" 46 #include "logging/log.hpp" 47 #include "logging/logTag.hpp" 48 #include "memory/oopFactory.hpp" 49 #include "memory/resourceArea.hpp" 50 #include "oops/constantPool.inline.hpp" 51 #include "oops/cpCache.inline.hpp" 52 #include "runtime/atomic.hpp" 53 #include "runtime/globals_extension.hpp" 54 #include "runtime/handles.inline.hpp" 55 #include "runtime/java.hpp" 56 #include "runtime/javaCalls.hpp" 57 #include "utilities/defaultStream.hpp" 58 #include "utilities/macros.hpp" 59 #include "utilities/utf8.hpp" 60 61 const char* ClassListParser::CLASS_REFLECTION_DATA_TAG = "@class-reflection-data"; 62 const char* ClassListParser::CONSTANT_POOL_TAG = "@cp"; 63 const char* ClassListParser::DYNAMIC_PROXY_TAG = "@dynamic-proxy"; 64 const char* ClassListParser::LAMBDA_FORM_TAG = "@lambda-form-invoker"; 65 const char* ClassListParser::LAMBDA_PROXY_TAG = "@lambda-proxy"; 66 const char* ClassListParser::LOADER_NEGATIVE_CACHE_TAG = "@loader-negative-cache"; 67 const char* ClassListParser::ARRAY_TAG = "@array"; 68 69 volatile Thread* ClassListParser::_parsing_thread = nullptr; 70 ClassListParser* ClassListParser::_instance = nullptr; 71 72 ClassListParser::ClassListParser(const char* file, ParseMode parse_mode) : 73 _classlist_file(file), 74 _id2klass_table(INITIAL_TABLE_SIZE, MAX_TABLE_SIZE), 75 _file_input(do_open(file), /* need_close=*/true), 76 _input_stream(&_file_input), 77 _parse_mode(parse_mode) { 78 aot_log_info(aot)("Parsing %s%s", file, 79 parse_lambda_forms_invokers_only() ? " (lambda form invokers only)" : ""); 80 if (!_file_input.is_open()) { 81 char reason[JVM_MAXPATHLEN]; 82 os::lasterror(reason, JVM_MAXPATHLEN); 83 vm_exit_during_initialization(err_msg("Loading %s %s failed", 84 FLAG_IS_DEFAULT(AOTConfiguration) ? 85 "classlist" : "AOTConfiguration file", 86 file), 87 reason); 88 } 89 _token = _line = nullptr; 90 _interfaces = new (mtClass) GrowableArray<int>(10, mtClass); 91 _indy_items = new (mtClass) GrowableArray<const char*>(9, mtClass); 92 93 // _instance should only be accessed by the thread that created _instance. 94 assert(_instance == nullptr, "must be singleton"); 95 _instance = this; 96 Atomic::store(&_parsing_thread, Thread::current()); 97 } 98 99 FILE* ClassListParser::do_open(const char* file) { 100 // Use os::open() because neither fopen() nor os::fopen() 101 // can handle long path name on Windows. (See JDK-8216184) 102 int fd = os::open(file, O_RDONLY, S_IREAD); 103 FILE* fp = nullptr; 104 if (fd != -1) { 105 // Obtain a FILE* from the file descriptor so that _input_stream 106 // can be used in ClassListParser::parse() 107 fp = os::fdopen(fd, "r"); 108 } 109 return fp; 110 } 111 112 bool ClassListParser::is_parsing_thread() { 113 return Atomic::load(&_parsing_thread) == Thread::current(); 114 } 115 116 ClassListParser::~ClassListParser() { 117 Atomic::store(&_parsing_thread, (Thread*)nullptr); 118 delete _indy_items; 119 delete _interfaces; 120 _instance = nullptr; 121 } 122 123 void ClassListParser::parse_classlist(const char* classlist_path, ParseMode parse_mode, TRAPS) { 124 UnregisteredClasses::initialize(CHECK); 125 ClassListParser parser(classlist_path, parse_mode); 126 parser.parse(THREAD); 127 } 128 129 void ClassListParser::parse(TRAPS) { 130 for (; !_input_stream.done(); _input_stream.next()) { 131 _line = _input_stream.current_line(); 132 clean_up_input_line(); 133 134 // Each line in the classlist can be one of three forms: 135 if (_line[0] == '#') { 136 // A comment; ignore it 137 } else if (_line[0] == '@') { 138 // @xxx - a tag like @lambda-proxy, to be parsed by parse_at_tags() 139 parse_at_tags(CHECK); 140 } else { 141 // A class name, followed by optional attributes. E.g. 142 // java/lang/String 143 // java/lang/Object id: 1 144 // my/pkg/TestClass id: 5 super: 1 interfaces: 3 4 source: foo.jar 145 parse_class_name_and_attributes(CHECK); 146 } 147 } 148 } 149 150 void ClassListParser::parse_class_name_and_attributes(TRAPS) { 151 read_class_name_and_attributes(); 152 153 if (parse_lambda_forms_invokers_only()) { 154 return; 155 } 156 157 check_class_name(_class_name); 158 TempNewSymbol class_name_symbol = SymbolTable::new_symbol(_class_name); 159 Klass* klass = load_current_class(class_name_symbol, THREAD); 160 if (HAS_PENDING_EXCEPTION) { 161 if (PENDING_EXCEPTION->is_a(vmClasses::OutOfMemoryError_klass())) { 162 // If we have run out of memory, don't try to load the rest of the classes in 163 // the classlist. Throw an exception, which will terminate the dumping process. 164 return; // THROW 165 } 166 167 ResourceMark rm(THREAD); 168 char* ex_msg = (char*)""; 169 oop message = java_lang_Throwable::message(PENDING_EXCEPTION); 170 if (message != nullptr) { 171 ex_msg = java_lang_String::as_utf8_string(message); 172 } 173 aot_log_warning(aot)("%s: %s", PENDING_EXCEPTION->klass()->external_name(), ex_msg); 174 // We might have an invalid class name or an bad class. Warn about it 175 // and keep going to the next line. 176 CLEAR_PENDING_EXCEPTION; 177 aot_log_warning(aot)("Preload Warning: Cannot find %s", _class_name); 178 return; 179 } 180 181 assert(klass != nullptr, "sanity"); 182 if (aot_log_is_enabled(Trace, aot)) { 183 ResourceMark rm(THREAD); 184 log_trace(aot)("Shared spaces preloaded: %s", klass->external_name()); 185 } 186 187 if (klass->is_instance_klass()) { 188 InstanceKlass* ik = InstanceKlass::cast(klass); 189 190 // Link the class to cause the bytecodes to be rewritten and the 191 // cpcache to be created. The linking is done as soon as classes 192 // are loaded in order that the related data structures (klass and 193 // cpCache) are located together. 194 MetaspaceShared::try_link_class(THREAD, ik); 195 } 196 } 197 198 void ClassListParser::clean_up_input_line() { 199 int len = (int)strlen(_line); 200 int i; 201 // Replace \t\r\n\f with ' ' 202 for (i=0; i<len; i++) { 203 if (_line[i] == '\t' || _line[i] == '\r' || _line[i] == '\n' || _line[i] == '\f') { 204 _line[i] = ' '; 205 } 206 } 207 208 // Remove trailing newline/space 209 while (len > 0) { 210 if (_line[len-1] == ' ') { 211 _line[len-1] = '\0'; 212 len --; 213 } else { 214 break; 215 } 216 } 217 _line_len = len; 218 } 219 220 void ClassListParser::read_class_name_and_attributes() { 221 _class_name = _line; 222 _id = _unspecified; 223 _super = _unspecified; 224 _interfaces->clear(); 225 _source = nullptr; 226 _interfaces_specified = false; 227 228 if ((_token = strchr(_line, ' ')) == nullptr) { 229 // No optional attributes are specified. 230 return; 231 } 232 233 // Mark the end of the name, and go to the next input char 234 *_token++ = '\0'; 235 236 while (*_token) { 237 skip_whitespaces(); 238 239 if (parse_uint_option("id:", &_id)) { 240 continue; 241 } else if (parse_uint_option("super:", &_super)) { 242 check_already_loaded("Super class", _super); 243 continue; 244 } else if (skip_token("interfaces:")) { 245 int i; 246 while (try_parse_uint(&i)) { 247 check_already_loaded("Interface", i); 248 _interfaces->append(i); 249 } 250 } else if (skip_token("source:")) { 251 skip_whitespaces(); 252 _source = _token; 253 char* s = strchr(_token, ' '); 254 if (s == nullptr) { 255 break; // end of input line 256 } else { 257 *s = '\0'; // mark the end of _source 258 _token = s+1; 259 } 260 } else { 261 error("Unknown input"); 262 } 263 } 264 265 // if src is specified 266 // id super interfaces must all be specified 267 // loader may be specified 268 // else 269 // # the class is loaded from classpath 270 // id may be specified 271 // super, interfaces, loader must not be specified 272 } 273 274 void ClassListParser::split_tokens_by_whitespace(int offset, GrowableArray<const char*>* items) { 275 int start = offset; 276 int end; 277 bool done = false; 278 while (!done) { 279 while (_line[start] == ' ' || _line[start] == '\t') start++; 280 end = start; 281 while (_line[end] && _line[end] != ' ' && _line[end] != '\t') end++; 282 if (_line[end] == '\0') { 283 done = true; 284 } else { 285 _line[end] = '\0'; 286 } 287 items->append(_line + start); 288 start = ++end; 289 } 290 } 291 292 int ClassListParser::split_at_tag_from_line() { 293 _token = _line; 294 char* ptr; 295 if ((ptr = strchr(_line, ' ')) == nullptr) { 296 error("Too few items following the @ tag \"%s\" line #%zu", _line, lineno()); 297 return 0; 298 } 299 *ptr++ = '\0'; 300 while (*ptr == ' ' || *ptr == '\t') ptr++; 301 return (int)(ptr - _line); 302 } 303 304 void ClassListParser::parse_at_tags(TRAPS) { 305 assert(_line[0] == '@', "must be"); 306 int offset = split_at_tag_from_line(); 307 assert(offset > 0, "would have exited VM"); 308 309 if (strcmp(_token, LAMBDA_PROXY_TAG) == 0) { 310 _indy_items->clear(); 311 split_tokens_by_whitespace(offset, _indy_items); 312 if (_indy_items->length() < 2) { 313 error("Line with @ tag has too few items \"%s\" line #%zu", _token, lineno()); 314 } 315 if (!parse_lambda_forms_invokers_only()) { 316 _class_name = _indy_items->at(0); 317 check_class_name(_class_name); 318 TempNewSymbol class_name_symbol = SymbolTable::new_symbol(_class_name); 319 if (_indy_items->length() > 0) { 320 // The current line is "@lambda-proxy class_name". Load the proxy class. 321 resolve_indy(THREAD, class_name_symbol); 322 } 323 } 324 } else if (strcmp(_token, LAMBDA_FORM_TAG) == 0) { 325 LambdaFormInvokers::append(os::strdup((const char*)(_line + offset), mtInternal)); 326 } else if (strcmp(_token, CONSTANT_POOL_TAG) == 0) { 327 _token = _line + offset; 328 parse_constant_pool_tag(); 329 } else if (strcmp(_token, ARRAY_TAG) == 0) { 330 _token = _line + offset; 331 parse_array_dimension_tag(); 332 } else if (strcmp(_token, CLASS_REFLECTION_DATA_TAG) == 0) { 333 _token = _line + offset; 334 parse_class_reflection_data_tag(); 335 } else if (strcmp(_token, DYNAMIC_PROXY_TAG) == 0) { 336 _token = _line + offset; 337 parse_dynamic_proxy_tag(); 338 } else if (strcmp(_token, LOADER_NEGATIVE_CACHE_TAG) == 0) { 339 _token = _line + offset; 340 parse_loader_negative_cache_tag(); 341 } else { 342 error("Invalid @ tag at the beginning of line \"%s\" line #%zu", _token, lineno()); 343 } 344 } 345 346 void ClassListParser::skip_whitespaces() { 347 while (*_token == ' ' || *_token == '\t') { 348 _token ++; 349 } 350 } 351 352 void ClassListParser::skip_non_whitespaces() { 353 while (*_token && *_token != ' ' && *_token != '\t') { 354 _token ++; 355 } 356 } 357 358 void ClassListParser::parse_int(int* value) { 359 skip_whitespaces(); 360 if (sscanf(_token, "%i", value) == 1) { 361 skip_non_whitespaces(); 362 } else { 363 error("Error: expected integer"); 364 } 365 } 366 367 void ClassListParser::parse_uint(int* value) { 368 parse_int(value); 369 if (*value < 0) { 370 error("Error: negative integers not allowed (%d)", *value); 371 } 372 } 373 374 bool ClassListParser::try_parse_uint(int* value) { 375 skip_whitespaces(); 376 if (sscanf(_token, "%i", value) == 1) { 377 skip_non_whitespaces(); 378 return true; 379 } 380 return false; 381 } 382 383 bool ClassListParser::skip_token(const char* option_name) { 384 size_t len = strlen(option_name); 385 if (strncmp(_token, option_name, len) == 0) { 386 _token += len; 387 return true; 388 } else { 389 return false; 390 } 391 } 392 393 bool ClassListParser::parse_int_option(const char* option_name, int* value) { 394 if (skip_token(option_name)) { 395 if (*value != _unspecified) { 396 error("%s specified twice", option_name); 397 } else { 398 parse_int(value); 399 return true; 400 } 401 } 402 return false; 403 } 404 405 bool ClassListParser::parse_uint_option(const char* option_name, int* value) { 406 if (skip_token(option_name)) { 407 if (*value != _unspecified) { 408 error("%s specified twice", option_name); 409 } else { 410 parse_uint(value); 411 return true; 412 } 413 } 414 return false; 415 } 416 417 GrowableArray<InstanceKlass *> ClassListParser::get_specified_interfaces() { 418 const int n = _interfaces->length(); 419 GrowableArray<InstanceKlass *> specified_interfaces(n); 420 for (int i = 0; i < n; i++) { 421 specified_interfaces.append(lookup_class_by_id(_interfaces->at(i))); 422 } 423 return specified_interfaces; 424 } 425 426 void ClassListParser::print_specified_interfaces() { 427 const int n = _interfaces->length(); 428 jio_fprintf(defaultStream::error_stream(), "Currently specified interfaces[%d] = {\n", n); 429 for (int i=0; i<n; i++) { 430 InstanceKlass* k = lookup_class_by_id(_interfaces->at(i)); 431 jio_fprintf(defaultStream::error_stream(), " %4d = %s\n", _interfaces->at(i), k->name()->as_klass_external_name()); 432 } 433 jio_fprintf(defaultStream::error_stream(), "}\n"); 434 } 435 436 void ClassListParser::print_actual_interfaces(InstanceKlass* ik) { 437 int n = ik->local_interfaces()->length(); 438 jio_fprintf(defaultStream::error_stream(), "Actual interfaces[%d] = {\n", n); 439 for (int i = 0; i < n; i++) { 440 InstanceKlass* e = ik->local_interfaces()->at(i); 441 jio_fprintf(defaultStream::error_stream(), " %s\n", e->name()->as_klass_external_name()); 442 } 443 jio_fprintf(defaultStream::error_stream(), "}\n"); 444 } 445 446 void ClassListParser::print_diagnostic_info(outputStream* st, const char* msg, ...) { 447 va_list ap; 448 va_start(ap, msg); 449 print_diagnostic_info(st, msg, ap); 450 va_end(ap); 451 } 452 453 void ClassListParser::print_diagnostic_info(outputStream* st, const char* msg, va_list ap) { 454 int error_index = pointer_delta_as_int(_token, _line); 455 if (error_index >= _line_len) { 456 error_index = _line_len - 1; 457 } 458 if (error_index < 0) { 459 error_index = 0; 460 } 461 462 st->print("An error has occurred while processing class list file %s %zu:%d.\n", 463 _classlist_file, lineno(), (error_index + 1)); 464 st->vprint(msg, ap); 465 466 if (_line_len <= 0) { 467 st->print("\n"); 468 } else { 469 st->print(":\n"); 470 for (int i=0; i<_line_len; i++) { 471 char c = _line[i]; 472 if (c == '\0') { 473 st->print("%s", " "); 474 } else { 475 st->print("%c", c); 476 } 477 } 478 st->print("\n"); 479 for (int i=0; i<error_index; i++) { 480 st->print("%s", " "); 481 } 482 st->print("^\n"); 483 } 484 } 485 486 void ClassListParser::error(const char* msg, ...) { 487 va_list ap; 488 va_start(ap, msg); 489 fileStream fs(defaultStream::error_stream()); 490 //TODO: we should write to UL/error instead, but that requires fixing some tests cases. 491 //LogTarget(Error, cds) lt; 492 //LogStream ls(lt); 493 print_diagnostic_info(&fs, msg, ap); 494 va_end(ap); 495 vm_exit_during_initialization("class list format error.", nullptr); 496 } 497 498 void ClassListParser::check_class_name(const char* class_name) { 499 const char* err = nullptr; 500 size_t len = strlen(class_name); 501 if (len > (size_t)Symbol::max_length()) { 502 err = "class name too long"; 503 } else { 504 assert(Symbol::max_length() < INT_MAX && len < INT_MAX, "must be"); 505 if (!UTF8::is_legal_utf8((const unsigned char*)class_name, len, /*version_leq_47*/false)) { 506 err = "class name is not valid UTF8"; 507 } 508 } 509 if (err != nullptr) { 510 jio_fprintf(defaultStream::error_stream(), 511 "An error has occurred while processing class list file %s:%zu %s\n", 512 _classlist_file, lineno(), err); 513 vm_exit_during_initialization("class list format error.", nullptr); 514 } 515 } 516 517 void ClassListParser::constant_pool_resolution_warning(const char* msg, ...) { 518 va_list ap; 519 va_start(ap, msg); 520 LogTarget(Warning, aot, resolve) lt; 521 LogStream ls(lt); 522 print_diagnostic_info(&ls, msg, ap); 523 ls.print("Your classlist may be out of sync with the JDK or the application."); 524 va_end(ap); 525 } 526 527 // If an unregistered class U is specified to have a registered supertype S1 528 // named SN but an unregistered class S2 also named SN has already been loaded 529 // S2 will be incorrectly used as the supertype of U instead of S1 due to 530 // limitations in the loading mechanism of unregistered classes. 531 void ClassListParser::check_supertype_obstruction(int specified_supertype_id, const InstanceKlass* specified_supertype, TRAPS) { 532 if (specified_supertype->defined_by_other_loaders()) { 533 return; // Only registered supertypes can be obstructed 534 } 535 const InstanceKlass* obstructor = SystemDictionaryShared::get_unregistered_class(specified_supertype->name()); 536 if (obstructor == nullptr) { 537 return; // No unregistered types with the same name have been loaded, i.e. no obstruction 538 } 539 // 'specified_supertype' is S1, 'obstructor' is S2 from the explanation above 540 ResourceMark rm; 541 THROW_MSG(vmSymbols::java_lang_UnsupportedOperationException(), 542 err_msg("%s (id %d) has super-type %s (id %d) obstructed by another class with the same name", 543 _class_name, _id, specified_supertype->external_name(), specified_supertype_id)); 544 } 545 546 // This function is used for loading classes for customized class loaders 547 // during archive dumping. 548 InstanceKlass* ClassListParser::load_class_from_source(Symbol* class_name, TRAPS) { 549 #if !(defined(_LP64) && (defined(LINUX) || defined(__APPLE__) || defined(_WINDOWS))) 550 // The only supported platforms are: (1) Linux/64-bit and (2) Solaris/64-bit and 551 // (3) MacOSX/64-bit and (4) Windowss/64-bit 552 // This #if condition should be in sync with the areCustomLoadersSupportedForCDS 553 // method in test/lib/jdk/test/lib/Platform.java. 554 error("AppCDS custom class loaders not supported on this platform"); 555 #endif 556 557 if (!is_super_specified()) { 558 error("If source location is specified, super class must be also specified"); 559 } 560 if (!is_id_specified()) { 561 error("If source location is specified, id must be also specified"); 562 } 563 if (strncmp(_class_name, "java/", 5) == 0) { 564 aot_log_info(aot)("Prohibited package for non-bootstrap classes: %s.class from %s", 565 _class_name, _source); 566 THROW_NULL(vmSymbols::java_lang_ClassNotFoundException()); 567 } 568 569 ResourceMark rm; 570 InstanceKlass* specified_super = lookup_class_by_id(_super); 571 GrowableArray<InstanceKlass*> specified_interfaces = get_specified_interfaces(); 572 // Obstruction must be checked before the class loading attempt because it may 573 // cause class loading errors (JVMS 5.3.5.3-5.3.5.4) 574 check_supertype_obstruction(_super, specified_super, CHECK_NULL); 575 for (int i = 0; i < _interfaces->length(); i++) { 576 check_supertype_obstruction(_interfaces->at(i), specified_interfaces.at(i), CHECK_NULL); 577 } 578 579 const char* source_path = ClassLoader::uri_to_path(_source); 580 InstanceKlass* k = UnregisteredClasses::load_class(class_name, source_path, CHECK_NULL); 581 582 if (k->java_super() != specified_super) { 583 error("The specified super class %s (id %d) does not match actual super class %s", 584 specified_super->external_name(), _super, 585 k->java_super()->external_name()); 586 } 587 if (k->local_interfaces()->length() != _interfaces->length()) { 588 print_specified_interfaces(); 589 print_actual_interfaces(k); 590 error("The number of interfaces (%d) specified in class list does not match the class file (%d)", 591 _interfaces->length(), k->local_interfaces()->length()); 592 } 593 for (int i = 0; i < _interfaces->length(); i++) { 594 InstanceKlass* specified_interface = specified_interfaces.at(i); 595 if (!k->local_interfaces()->contains(specified_interface)) { 596 print_specified_interfaces(); 597 print_actual_interfaces(k); 598 error("Specified interface %s (id %d) is not directly implemented", 599 specified_interface->external_name(), _interfaces->at(i)); 600 } 601 } 602 603 assert(k->defined_by_other_loaders(), "must be"); 604 605 bool added = SystemDictionaryShared::add_unregistered_class(THREAD, k); 606 if (!added) { 607 // We allow only a single unregistered class for each unique name. 608 error("Duplicated class %s", _class_name); 609 } 610 611 return k; 612 } 613 614 void ClassListParser::populate_cds_indy_info(const constantPoolHandle &pool, int cp_index, CDSIndyInfo* cii, TRAPS) { 615 // Caller needs to allocate ResourceMark. 616 int type_index = pool->bootstrap_name_and_type_ref_index_at(cp_index); 617 int name_index = pool->name_ref_index_at(type_index); 618 cii->add_item(pool->symbol_at(name_index)->as_C_string()); 619 int sig_index = pool->signature_ref_index_at(type_index); 620 cii->add_item(pool->symbol_at(sig_index)->as_C_string()); 621 int argc = pool->bootstrap_argument_count_at(cp_index); 622 if (argc > 0) { 623 for (int arg_i = 0; arg_i < argc; arg_i++) { 624 int arg = pool->bootstrap_argument_index_at(cp_index, arg_i); 625 jbyte tag = pool->tag_at(arg).value(); 626 if (tag == JVM_CONSTANT_MethodType) { 627 cii->add_item(pool->method_type_signature_at(arg)->as_C_string()); 628 } else if (tag == JVM_CONSTANT_MethodHandle) { 629 cii->add_ref_kind(pool->method_handle_ref_kind_at(arg)); 630 int callee_index = pool->method_handle_klass_index_at(arg); 631 Klass* callee = pool->klass_at(callee_index, CHECK); 632 cii->add_item(callee->name()->as_C_string()); 633 cii->add_item(pool->method_handle_name_ref_at(arg)->as_C_string()); 634 cii->add_item(pool->method_handle_signature_ref_at(arg)->as_C_string()); 635 } else { 636 ShouldNotReachHere(); 637 } 638 } 639 } 640 } 641 642 bool ClassListParser::is_matching_cp_entry(const constantPoolHandle &pool, int cp_index, TRAPS) { 643 ResourceMark rm(THREAD); 644 CDSIndyInfo cii; 645 populate_cds_indy_info(pool, cp_index, &cii, CHECK_0); 646 GrowableArray<const char*>* items = cii.items(); 647 int indy_info_offset = 1; 648 if (_indy_items->length() - indy_info_offset != items->length()) { 649 return false; 650 } 651 for (int i = 0; i < items->length(); i++) { 652 if (strcmp(_indy_items->at(i + indy_info_offset), items->at(i)) != 0) { 653 return false; 654 } 655 } 656 return true; 657 } 658 659 void ClassListParser::resolve_indy(JavaThread* current, Symbol* class_name_symbol) { 660 ExceptionMark em(current); 661 JavaThread* THREAD = current; // For exception macros. 662 ClassListParser::resolve_indy_impl(class_name_symbol, THREAD); 663 if (HAS_PENDING_EXCEPTION) { 664 ResourceMark rm(current); 665 char* ex_msg = (char*)""; 666 oop message = java_lang_Throwable::message(PENDING_EXCEPTION); 667 if (message != nullptr) { 668 ex_msg = java_lang_String::as_utf8_string(message); 669 } 670 aot_log_warning(aot)("resolve_indy for class %s has encountered exception: %s %s", 671 class_name_symbol->as_C_string(), 672 PENDING_EXCEPTION->klass()->external_name(), 673 ex_msg); 674 CLEAR_PENDING_EXCEPTION; 675 } 676 } 677 678 void ClassListParser::resolve_indy_impl(Symbol* class_name_symbol, TRAPS) { 679 if (CDSConfig::is_dumping_method_handles()) { 680 // The CP entry for the invokedynamic instruction will be resolved. 681 // No need to do the following. 682 return; 683 } 684 685 // This is an older CDS optimization: 686 // We store a pre-generated version of the lambda proxy class in the AOT cache, 687 // which will be loaded via JVM_LookupLambdaProxyClassFromArchive(). 688 // This eliminate dynamic class generation of the proxy class, but we still need to 689 // resolve the CP entry for the invokedynamic instruction, which may result in 690 // generation of LambdaForm classes. 691 Handle class_loader(THREAD, SystemDictionary::java_system_loader()); 692 Klass* klass = SystemDictionary::resolve_or_fail(class_name_symbol, class_loader, true, CHECK); 693 if (klass->is_instance_klass()) { 694 InstanceKlass* ik = InstanceKlass::cast(klass); 695 MetaspaceShared::try_link_class(THREAD, ik); 696 if (!ik->is_linked()) { 697 // Verification of ik has failed 698 return; 699 } 700 701 ConstantPool* cp = ik->constants(); 702 ConstantPoolCache* cpcache = cp->cache(); 703 bool found = false; 704 for (int indy_index = 0; indy_index < cpcache->resolved_indy_entries_length(); indy_index++) { 705 int pool_index = cpcache->resolved_indy_entry_at(indy_index)->constant_pool_index(); 706 constantPoolHandle pool(THREAD, cp); 707 BootstrapInfo bootstrap_specifier(pool, pool_index, indy_index); 708 Handle bsm = bootstrap_specifier.resolve_bsm(CHECK); 709 if (!LambdaProxyClassDictionary::is_supported_invokedynamic(&bootstrap_specifier)) { 710 log_debug(aot, lambda)("is_supported_invokedynamic check failed for cp_index %d", pool_index); 711 continue; 712 } 713 bool matched = is_matching_cp_entry(pool, pool_index, CHECK); 714 if (matched) { 715 found = true; 716 CallInfo info; 717 bool is_done = bootstrap_specifier.resolve_previously_linked_invokedynamic(info, CHECK); 718 if (!is_done) { 719 // resolve it 720 Handle recv; 721 LinkResolver::resolve_invoke(info, 722 recv, 723 pool, 724 indy_index, 725 Bytecodes::_invokedynamic, CHECK); 726 break; 727 } 728 cpcache->set_dynamic_call(info, indy_index); 729 } 730 } 731 if (!found) { 732 ResourceMark rm(THREAD); 733 aot_log_warning(aot)("No invoke dynamic constant pool entry can be found for class %s. The classlist is probably out-of-date.", 734 class_name_symbol->as_C_string()); 735 } 736 } 737 } 738 739 Klass* ClassListParser::load_current_class(Symbol* class_name_symbol, TRAPS) { 740 Klass* klass; 741 if (!is_loading_from_source()) { 742 // Load classes for the boot/platform/app loaders only. 743 if (is_super_specified()) { 744 error("If source location is not specified, super class must not be specified"); 745 } 746 if (are_interfaces_specified()) { 747 error("If source location is not specified, interface(s) must not be specified"); 748 } 749 750 if (Signature::is_array(class_name_symbol)) { 751 // array classes are not supported in class list. 752 THROW_NULL(vmSymbols::java_lang_ClassNotFoundException()); 753 } 754 755 JavaValue result(T_OBJECT); 756 // Call java_system_loader().loadClass() directly, which will 757 // delegate to the correct loader (boot, platform or app) depending on 758 // the package name. 759 760 // ClassLoader.loadClass() wants external class name format, i.e., convert '/' chars to '.' 761 Handle ext_class_name = java_lang_String::externalize_classname(class_name_symbol, CHECK_NULL); 762 Handle loader = Handle(THREAD, SystemDictionary::java_system_loader()); 763 764 JavaCalls::call_virtual(&result, 765 loader, //SystemDictionary::java_system_loader(), 766 vmClasses::ClassLoader_klass(), 767 vmSymbols::loadClass_name(), 768 vmSymbols::string_class_signature(), 769 ext_class_name, 770 CHECK_NULL); 771 772 assert(result.get_type() == T_OBJECT, "just checking"); 773 oop obj = result.get_oop(); 774 assert(obj != nullptr, "jdk.internal.loader.BuiltinClassLoader::loadClass never returns null"); 775 klass = java_lang_Class::as_Klass(obj); 776 } else { 777 // If "source:" tag is specified, all super class and super interfaces must be specified in the 778 // class list file. 779 klass = load_class_from_source(class_name_symbol, CHECK_NULL); 780 } 781 782 assert(klass != nullptr, "exception should have been thrown"); 783 assert(klass->is_instance_klass(), "array classes should have been filtered out"); 784 785 if (is_id_specified()) { 786 InstanceKlass* ik = InstanceKlass::cast(klass); 787 int id = this->id(); 788 SystemDictionaryShared::update_shared_entry(ik, id); 789 bool created; 790 id2klass_table()->put_if_absent(id, ik, &created); 791 if (!created) { 792 error("Duplicated ID %d for class %s", id, _class_name); 793 } 794 if (id2klass_table()->maybe_grow()) { 795 log_info(aot, hashtables)("Expanded id2klass_table() to %d", id2klass_table()->table_size()); 796 } 797 } 798 799 return klass; 800 } 801 802 bool ClassListParser::is_loading_from_source() { 803 return (_source != nullptr); 804 } 805 806 InstanceKlass* ClassListParser::lookup_class_by_id(int id) { 807 InstanceKlass** klass_ptr = id2klass_table()->get(id); 808 if (klass_ptr == nullptr) { 809 error("Class ID %d has not been defined", id); 810 } 811 assert(*klass_ptr != nullptr, "must be"); 812 return *klass_ptr; 813 } 814 815 InstanceKlass* ClassListParser::find_builtin_class_helper(JavaThread* current, Symbol* class_name_symbol, oop class_loader_oop) { 816 Handle class_loader(current, class_loader_oop); 817 return SystemDictionary::find_instance_klass(current, class_name_symbol, class_loader); 818 } 819 820 InstanceKlass* ClassListParser::find_builtin_class(JavaThread* current, const char* class_name) { 821 TempNewSymbol class_name_symbol = SymbolTable::new_symbol(class_name); 822 InstanceKlass* ik; 823 824 if ( (ik = find_builtin_class_helper(current, class_name_symbol, nullptr)) != nullptr 825 || (ik = find_builtin_class_helper(current, class_name_symbol, SystemDictionary::java_platform_loader())) != nullptr 826 || (ik = find_builtin_class_helper(current, class_name_symbol, SystemDictionary::java_system_loader())) != nullptr) { 827 return ik; 828 } else { 829 return nullptr; 830 } 831 } 832 833 void ClassListParser::parse_array_dimension_tag() { 834 if (parse_lambda_forms_invokers_only()) { 835 return; 836 } 837 838 skip_whitespaces(); 839 char* class_name = _token; 840 skip_non_whitespaces(); 841 *_token = '\0'; 842 _token ++; 843 844 skip_whitespaces(); 845 int dim; 846 parse_uint(&dim); 847 848 JavaThread* THREAD = JavaThread::current(); 849 InstanceKlass* ik = find_builtin_class(THREAD, class_name); 850 if (ik == nullptr) { 851 _token = class_name; 852 if (strstr(class_name, "/$Proxy") != nullptr || 853 strstr(class_name, "MethodHandle$Species_") != nullptr) { 854 // ignore -- TODO: we should filter these out in classListWriter.cpp 855 } else { 856 constant_pool_resolution_warning("class %s is not (yet) loaded by one of the built-in loaders", class_name); 857 } 858 return; 859 } 860 861 if (dim > 0) { 862 ik->array_klass(dim, THREAD); 863 if (HAS_PENDING_EXCEPTION) { 864 error("Array klass allocation failed: %s %d", _class_name, dim); 865 } 866 } 867 } 868 869 void ClassListParser::parse_constant_pool_tag() { 870 if (parse_lambda_forms_invokers_only()) { 871 return; 872 } 873 874 JavaThread* THREAD = JavaThread::current(); 875 skip_whitespaces(); 876 char* class_name = _token; 877 skip_non_whitespaces(); 878 *_token = '\0'; 879 _token ++; 880 881 InstanceKlass* ik = find_builtin_class(THREAD, class_name); 882 if (ik == nullptr) { 883 _token = class_name; 884 if (strstr(class_name, "/$Proxy") != nullptr || 885 strstr(class_name, "MethodHandle$Species_") != nullptr) { 886 // ignore -- TODO: we should filter these out in classListWriter.cpp 887 } else { 888 constant_pool_resolution_warning("class %s is not (yet) loaded by one of the built-in loaders", class_name); 889 } 890 return; 891 } 892 893 ResourceMark rm(THREAD); 894 constantPoolHandle cp(THREAD, ik->constants()); 895 GrowableArray<bool> preresolve_list(cp->length(), cp->length(), false); 896 bool preresolve_class = false; 897 bool preresolve_fmi = false; 898 bool preresolve_indy = false; 899 900 while (*_token) { 901 int cp_index; 902 skip_whitespaces(); 903 parse_uint(&cp_index); 904 if (cp_index < 1 || cp_index >= cp->length()) { 905 constant_pool_resolution_warning("Invalid constant pool index %d", cp_index); 906 return; 907 } else { 908 preresolve_list.at_put(cp_index, true); 909 } 910 constantTag cp_tag = cp->tag_at(cp_index); 911 switch (cp_tag.value()) { 912 case JVM_CONSTANT_UnresolvedClass: 913 preresolve_class = true; 914 break; 915 case JVM_CONSTANT_UnresolvedClassInError: 916 case JVM_CONSTANT_Class: 917 // ignore 918 break; 919 case JVM_CONSTANT_Fieldref: 920 case JVM_CONSTANT_Methodref: 921 case JVM_CONSTANT_InterfaceMethodref: 922 preresolve_fmi = true; 923 break; 924 case JVM_CONSTANT_InvokeDynamic: 925 preresolve_indy = true; 926 break; 927 default: 928 constant_pool_resolution_warning("Unsupported constant pool index %d: %s (type=%d)", 929 cp_index, cp_tag.internal_name(), cp_tag.value()); 930 return; 931 } 932 } 933 934 if (SystemDictionaryShared::should_be_excluded(ik)) { 935 if (log_is_enabled(Warning, aot, resolve)) { 936 ResourceMark rm; 937 log_warning(aot, resolve)("Cannot aot-resolve constants for %s because it is excluded", ik->external_name()); 938 } 939 return; 940 } 941 942 if (preresolve_class) { 943 AOTConstantPoolResolver::preresolve_class_cp_entries(THREAD, ik, &preresolve_list); 944 } 945 if (preresolve_fmi) { 946 // FIXME: too coarse; doesn't cover resolution of Class entries 947 // JavaThread::NoJavaCodeMark no_java_code(THREAD); // ensure no clinits are exectued 948 AOTConstantPoolResolver::preresolve_field_and_method_cp_entries(THREAD, ik, &preresolve_list); 949 } 950 if (preresolve_indy) { 951 AOTConstantPoolResolver::preresolve_indy_cp_entries(THREAD, ik, &preresolve_list); 952 } 953 } 954 955 void ClassListParser::parse_class_reflection_data_tag() { 956 if (parse_lambda_forms_invokers_only()) { 957 return; 958 } 959 960 JavaThread* THREAD = JavaThread::current(); 961 skip_whitespaces(); 962 char* class_name = _token; 963 skip_non_whitespaces(); 964 *_token = '\0'; 965 _token ++; 966 967 InstanceKlass* ik = find_builtin_class(THREAD, class_name); 968 if (ik == nullptr) { 969 _token = class_name; 970 if (strstr(class_name, "/$Proxy") != nullptr || 971 strstr(class_name, "MethodHandle$Species_") != nullptr) { 972 // ignore -- TODO: we should filter these out in classListWriter.cpp 973 } else { 974 warning("%s: class not found: %s", CLASS_REFLECTION_DATA_TAG, class_name); 975 } 976 return; 977 } 978 979 ResourceMark rm(THREAD); 980 981 int rd_flags = _unspecified; 982 while (*_token) { 983 skip_whitespaces(); 984 if (rd_flags != _unspecified) { 985 error("rd_flags specified twice"); 986 return; 987 } 988 parse_uint(&rd_flags); 989 } 990 if (rd_flags == _unspecified) { 991 error("no rd_flags specified"); 992 return; 993 } 994 995 if (CDSConfig::is_dumping_reflection_data()) { 996 AOTConstantPoolResolver::generate_reflection_data(THREAD, ik, rd_flags); 997 } 998 } 999 1000 oop ClassListParser::loader_from_type(const char* loader_type) { 1001 oop loader; 1002 if (!ArchiveUtils::builtin_loader_from_type(loader_type, &loader)) { 1003 error("Unknown loader %s", loader_type); 1004 } 1005 return loader; 1006 } 1007 1008 void ClassListParser::parse_dynamic_proxy_tag() { 1009 if (parse_lambda_forms_invokers_only()) { 1010 return; 1011 } 1012 1013 skip_whitespaces(); 1014 char* loader_type = _token; 1015 skip_non_whitespaces(); 1016 *_token = '\0'; 1017 _token ++; 1018 1019 skip_whitespaces(); 1020 char* proxy_name_str = _token; 1021 skip_non_whitespaces(); 1022 *_token = '\0'; 1023 _token ++; 1024 1025 skip_whitespaces(); 1026 int access_flags; 1027 parse_uint(&access_flags); 1028 1029 skip_whitespaces(); 1030 int num_intfs; 1031 parse_uint(&num_intfs); 1032 1033 JavaThread* THREAD = JavaThread::current(); 1034 Handle loader(THREAD, loader_from_type(loader_type)); 1035 Handle proxy_name(THREAD, java_lang_String::create_oop_from_str(proxy_name_str, THREAD)); 1036 if (HAS_PENDING_EXCEPTION) { 1037 error("Out of memory"); 1038 } 1039 1040 objArrayHandle interfaces(THREAD, oopFactory::new_objArray(vmClasses::Class_klass(), num_intfs, THREAD)); 1041 if (HAS_PENDING_EXCEPTION) { 1042 error("Out of memory"); 1043 } 1044 1045 for (int i = 0; i < num_intfs; i++) { 1046 skip_whitespaces(); 1047 char* intf_name = _token; 1048 skip_non_whitespaces(); 1049 *_token = '\0'; 1050 _token ++; 1051 1052 InstanceKlass* ik = find_builtin_class(THREAD, intf_name); 1053 if (ik != nullptr) { 1054 interfaces()->obj_at_put(i, ik->java_mirror()); 1055 } else { 1056 error("Unknown class %s", intf_name); 1057 } 1058 } 1059 1060 if (strncmp("jdk.proxy", proxy_name_str, 9) != 0) { 1061 return; 1062 } 1063 1064 AOTConstantPoolResolver::define_dynamic_proxy_class(loader, proxy_name, interfaces, access_flags, THREAD); 1065 if (HAS_PENDING_EXCEPTION) { 1066 PENDING_EXCEPTION->print_on(tty); 1067 error("defineProxyClassForCDS failed"); 1068 } 1069 } 1070 1071 void ClassListParser::parse_loader_negative_cache_tag() { 1072 skip_whitespaces(); 1073 char* loader_type = _token; 1074 skip_non_whitespaces(); 1075 *_token = '\0'; 1076 _token ++; 1077 1078 oop loader; 1079 Klass* loader_klass; 1080 if (!strcmp(loader_type, "app")) { 1081 loader = SystemDictionary::java_system_loader(); 1082 loader_klass = vmClasses::jdk_internal_loader_ClassLoaders_AppClassLoader_klass(); 1083 } else if (!strcmp(loader_type, "platform")) { 1084 loader = SystemDictionary::java_platform_loader(); 1085 loader_klass = vmClasses::jdk_internal_loader_ClassLoaders_PlatformClassLoader_klass(); 1086 } else { 1087 warning("%s: unrecognized loader type %s is ignored", LOADER_NEGATIVE_CACHE_TAG, loader_type); 1088 return; 1089 } 1090 1091 char* contents = _token; 1092 skip_non_whitespaces(); 1093 *_token = '\0'; 1094 _token ++; 1095 1096 if (ArchiveLoaderLookupCache) { 1097 TempNewSymbol method = SymbolTable::new_symbol("generateNegativeLookupCache"); 1098 TempNewSymbol signature = SymbolTable::new_symbol("(Ljava/lang/String;)V"); 1099 1100 EXCEPTION_MARK; 1101 HandleMark hm(THREAD); 1102 JavaCallArguments args(Handle(THREAD, loader)); 1103 Handle contents_h = java_lang_String::create_from_str(contents, THREAD); 1104 args.push_oop(contents_h); 1105 JavaValue result(T_VOID); 1106 JavaCalls::call_virtual(&result, 1107 loader_klass, 1108 method, 1109 signature, 1110 &args, THREAD); 1111 if (HAS_PENDING_EXCEPTION) { 1112 Handle exc_handle(THREAD, PENDING_EXCEPTION); 1113 CLEAR_PENDING_EXCEPTION; 1114 1115 log_warning(cds)("Exception during BuiltinClassLoader::generateNegativeLookupCache() call for %s loader", loader_type); 1116 LogStreamHandle(Debug, cds) log; 1117 if (log.is_enabled()) { 1118 java_lang_Throwable::print_stack_trace(exc_handle, &log); 1119 } 1120 } 1121 } 1122 } 1123