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/aotMetaspace.hpp"
28 #include "cds/archiveUtils.hpp"
29 #include "cds/cdsConfig.hpp"
30 #include "cds/classListParser.hpp"
31 #include "cds/lambdaFormInvokers.hpp"
32 #include "cds/lambdaProxyClassDictionary.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/atomicAccess.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 AtomicAccess::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 AtomicAccess::load(&_parsing_thread) == Thread::current();
114 }
115
116 ClassListParser::~ClassListParser() {
117 AtomicAccess::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 AOTMetaspace::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->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->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 AOTMetaspace::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