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