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