7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 #include "precompiled.hpp"
26 #include "cds/archiveUtils.hpp"
27 #include "cds/classListParser.hpp"
28 #include "cds/lambdaFormInvokers.hpp"
29 #include "cds/metaspaceShared.hpp"
30 #include "cds/unregisteredClasses.hpp"
31 #include "classfile/classLoaderExt.hpp"
32 #include "classfile/javaClasses.inline.hpp"
33 #include "classfile/symbolTable.hpp"
34 #include "classfile/systemDictionary.hpp"
35 #include "classfile/systemDictionaryShared.hpp"
36 #include "classfile/vmClasses.hpp"
37 #include "classfile/vmSymbols.hpp"
38 #include "interpreter/bytecode.hpp"
39 #include "interpreter/bytecodeStream.hpp"
40 #include "interpreter/linkResolver.hpp"
41 #include "jimage.hpp"
42 #include "jvm.h"
43 #include "logging/log.hpp"
44 #include "logging/logTag.hpp"
45 #include "memory/resourceArea.hpp"
46 #include "oops/constantPool.inline.hpp"
47 #include "runtime/atomic.hpp"
48 #include "runtime/handles.inline.hpp"
49 #include "runtime/java.hpp"
50 #include "runtime/javaCalls.hpp"
51 #include "utilities/defaultStream.hpp"
52 #include "utilities/macros.hpp"
53 #include "utilities/utf8.hpp"
54
55 volatile Thread* ClassListParser::_parsing_thread = nullptr;
56 ClassListParser* ClassListParser::_instance = nullptr;
57
58 ClassListParser::ClassListParser(const char* file, ParseMode parse_mode) :
59 _classlist_file(file),
60 _id2klass_table(INITIAL_TABLE_SIZE, MAX_TABLE_SIZE),
61 _file_input(do_open(file), /* need_close=*/true),
62 _input_stream(&_file_input) {
63 log_info(cds)("Parsing %s%s", file,
64 parse_lambda_forms_invokers_only() ? " (lambda form invokers only)" : "");
65 if (!_file_input.is_open()) {
66 char errmsg[JVM_MAXPATHLEN];
67 os::lasterror(errmsg, JVM_MAXPATHLEN);
68 vm_exit_during_initialization("Loading classlist failed", errmsg);
69 }
70 _token = _line = nullptr;
71 _interfaces = new (mtClass) GrowableArray<int>(10, mtClass);
72 _indy_items = new (mtClass) GrowableArray<const char*>(9, mtClass);
73 _parse_mode = parse_mode;
74
282 int offset = split_at_tag_from_line();
283 assert(offset > 0, "would have exited VM");
284
285 if (strcmp(_token, LAMBDA_PROXY_TAG) == 0) {
286 _indy_items->clear();
287 split_tokens_by_whitespace(offset, _indy_items);
288 if (_indy_items->length() < 2) {
289 error("Line with @ tag has too few items \"%s\" line #%zu", _token, lineno());
290 }
291 if (!parse_lambda_forms_invokers_only()) {
292 _class_name = _indy_items->at(0);
293 check_class_name(_class_name);
294 TempNewSymbol class_name_symbol = SymbolTable::new_symbol(_class_name);
295 if (_indy_items->length() > 0) {
296 // The current line is "@lambda-proxy class_name". Load the proxy class.
297 resolve_indy(THREAD, class_name_symbol);
298 }
299 }
300 } else if (strcmp(_token, LAMBDA_FORM_TAG) == 0) {
301 LambdaFormInvokers::append(os::strdup((const char*)(_line + offset), mtInternal));
302 } else {
303 error("Invalid @ tag at the beginning of line \"%s\" line #%zu", _token, lineno());
304 }
305 }
306
307 void ClassListParser::skip_whitespaces() {
308 while (*_token == ' ' || *_token == '\t') {
309 _token ++;
310 }
311 }
312
313 void ClassListParser::skip_non_whitespaces() {
314 while (*_token && *_token != ' ' && *_token != '\t') {
315 _token ++;
316 }
317 }
318
319 void ClassListParser::parse_int(int* value) {
320 skip_whitespaces();
321 if (sscanf(_token, "%i", value) == 1) {
378 void ClassListParser::print_specified_interfaces() {
379 const int n = _interfaces->length();
380 jio_fprintf(defaultStream::error_stream(), "Currently specified interfaces[%d] = {\n", n);
381 for (int i=0; i<n; i++) {
382 InstanceKlass* k = lookup_class_by_id(_interfaces->at(i));
383 jio_fprintf(defaultStream::error_stream(), " %4d = %s\n", _interfaces->at(i), k->name()->as_klass_external_name());
384 }
385 jio_fprintf(defaultStream::error_stream(), "}\n");
386 }
387
388 void ClassListParser::print_actual_interfaces(InstanceKlass* ik) {
389 int n = ik->local_interfaces()->length();
390 jio_fprintf(defaultStream::error_stream(), "Actual interfaces[%d] = {\n", n);
391 for (int i = 0; i < n; i++) {
392 InstanceKlass* e = ik->local_interfaces()->at(i);
393 jio_fprintf(defaultStream::error_stream(), " %s\n", e->name()->as_klass_external_name());
394 }
395 jio_fprintf(defaultStream::error_stream(), "}\n");
396 }
397
398 void ClassListParser::error(const char* msg, ...) {
399 va_list ap;
400 va_start(ap, msg);
401 int error_index = pointer_delta_as_int(_token, _line);
402 if (error_index >= _line_len) {
403 error_index = _line_len - 1;
404 }
405 if (error_index < 0) {
406 error_index = 0;
407 }
408
409 jio_fprintf(defaultStream::error_stream(),
410 "An error has occurred while processing class list file %s %zu:%d.\n",
411 _classlist_file, lineno(), (error_index + 1));
412 jio_vfprintf(defaultStream::error_stream(), msg, ap);
413
414 if (_line_len <= 0) {
415 jio_fprintf(defaultStream::error_stream(), "\n");
416 } else {
417 jio_fprintf(defaultStream::error_stream(), ":\n");
418 for (int i=0; i<_line_len; i++) {
419 char c = _line[i];
420 if (c == '\0') {
421 jio_fprintf(defaultStream::error_stream(), "%s", " ");
422 } else {
423 jio_fprintf(defaultStream::error_stream(), "%c", c);
424 }
425 }
426 jio_fprintf(defaultStream::error_stream(), "\n");
427 for (int i=0; i<error_index; i++) {
428 jio_fprintf(defaultStream::error_stream(), "%s", " ");
429 }
430 jio_fprintf(defaultStream::error_stream(), "^\n");
431 }
432 va_end(ap);
433
434 vm_exit_during_initialization("class list format error.", nullptr);
435 }
436
437 void ClassListParser::check_class_name(const char* class_name) {
438 const char* err = nullptr;
439 size_t len = strlen(class_name);
440 if (len > (size_t)Symbol::max_length()) {
441 err = "class name too long";
442 } else {
443 assert(Symbol::max_length() < INT_MAX && len < INT_MAX, "must be");
444 if (!UTF8::is_legal_utf8((const unsigned char*)class_name, (int)len, /*version_leq_47*/false)) {
445 err = "class name is not valid UTF8";
446 }
447 }
448 if (err != nullptr) {
449 jio_fprintf(defaultStream::error_stream(),
450 "An error has occurred while processing class list file %s:%zu %s\n",
451 _classlist_file, lineno(), err);
452 vm_exit_during_initialization("class list format error.", nullptr);
453 }
454 }
455
456 // This function is used for loading classes for customized class loaders
457 // during archive dumping.
458 InstanceKlass* ClassListParser::load_class_from_source(Symbol* class_name, TRAPS) {
459 #if !(defined(_LP64) && (defined(LINUX) || defined(__APPLE__) || defined(_WINDOWS)))
460 // The only supported platforms are: (1) Linux/64-bit and (2) Solaris/64-bit and
461 // (3) MacOSX/64-bit and (4) Windowss/64-bit
462 // This #if condition should be in sync with the areCustomLoadersSupportedForCDS
463 // method in test/lib/jdk/test/lib/Platform.java.
464 error("AppCDS custom class loaders not supported on this platform");
465 #endif
466
467 if (!is_super_specified()) {
468 error("If source location is specified, super class must be also specified");
469 }
470 if (!is_id_specified()) {
471 error("If source location is specified, id must be also specified");
472 }
473 if (strncmp(_class_name, "java/", 5) == 0) {
474 log_info(cds)("Prohibited package for non-bootstrap classes: %s.class from %s",
475 _class_name, _source);
710 error("Class %s implements the interface %s, but no interface has been specified in the input line",
711 _class_name, interface_name->as_klass_external_name());
712 ShouldNotReachHere();
713 }
714
715 int i;
716 for (i=0; i<n; i++) {
717 InstanceKlass* k = lookup_class_by_id(_interfaces->at(i));
718 if (interface_name == k->name()) {
719 return k;
720 }
721 }
722
723 // interface_name is not specified by the "interfaces:" keyword.
724 print_specified_interfaces();
725 error("The interface %s implemented by class %s does not match any of the specified interface IDs",
726 interface_name->as_klass_external_name(), _class_name);
727 ShouldNotReachHere();
728 return nullptr;
729 }
|
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 #include "precompiled.hpp"
26 #include "cds/archiveUtils.hpp"
27 #include "cds/cdsConfig.hpp"
28 #include "cds/classListParser.hpp"
29 #include "cds/classPrelinker.hpp"
30 #include "cds/lambdaFormInvokers.hpp"
31 #include "cds/metaspaceShared.hpp"
32 #include "cds/unregisteredClasses.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/handles.inline.hpp"
52 #include "runtime/java.hpp"
53 #include "runtime/javaCalls.hpp"
54 #include "utilities/defaultStream.hpp"
55 #include "utilities/macros.hpp"
56 #include "utilities/utf8.hpp"
57
58 const char* ClassListParser::CLASS_REFLECTION_DATA_TAG = "@class-reflection-data";
59 const char* ClassListParser::CONSTANT_POOL_TAG = "@cp";
60 const char* ClassListParser::DYNAMIC_PROXY_TAG = "@dynamic-proxy";
61 const char* ClassListParser::LAMBDA_FORM_TAG = "@lambda-form-invoker";
62 const char* ClassListParser::LAMBDA_PROXY_TAG = "@lambda-proxy";
63 const char* ClassListParser::LOADER_NEGATIVE_CACHE_TAG = "@loader-negative-cache";
64 const char* ClassListParser::ARRAY_TAG = "@array";
65
66 volatile Thread* ClassListParser::_parsing_thread = nullptr;
67 ClassListParser* ClassListParser::_instance = nullptr;
68
69 ClassListParser::ClassListParser(const char* file, ParseMode parse_mode) :
70 _classlist_file(file),
71 _id2klass_table(INITIAL_TABLE_SIZE, MAX_TABLE_SIZE),
72 _file_input(do_open(file), /* need_close=*/true),
73 _input_stream(&_file_input) {
74 log_info(cds)("Parsing %s%s", file,
75 parse_lambda_forms_invokers_only() ? " (lambda form invokers only)" : "");
76 if (!_file_input.is_open()) {
77 char errmsg[JVM_MAXPATHLEN];
78 os::lasterror(errmsg, JVM_MAXPATHLEN);
79 vm_exit_during_initialization("Loading classlist failed", errmsg);
80 }
81 _token = _line = nullptr;
82 _interfaces = new (mtClass) GrowableArray<int>(10, mtClass);
83 _indy_items = new (mtClass) GrowableArray<const char*>(9, mtClass);
84 _parse_mode = parse_mode;
85
293 int offset = split_at_tag_from_line();
294 assert(offset > 0, "would have exited VM");
295
296 if (strcmp(_token, LAMBDA_PROXY_TAG) == 0) {
297 _indy_items->clear();
298 split_tokens_by_whitespace(offset, _indy_items);
299 if (_indy_items->length() < 2) {
300 error("Line with @ tag has too few items \"%s\" line #%zu", _token, lineno());
301 }
302 if (!parse_lambda_forms_invokers_only()) {
303 _class_name = _indy_items->at(0);
304 check_class_name(_class_name);
305 TempNewSymbol class_name_symbol = SymbolTable::new_symbol(_class_name);
306 if (_indy_items->length() > 0) {
307 // The current line is "@lambda-proxy class_name". Load the proxy class.
308 resolve_indy(THREAD, class_name_symbol);
309 }
310 }
311 } else if (strcmp(_token, LAMBDA_FORM_TAG) == 0) {
312 LambdaFormInvokers::append(os::strdup((const char*)(_line + offset), mtInternal));
313 } else if (strcmp(_token, CONSTANT_POOL_TAG) == 0) {
314 _token = _line + offset;
315 parse_constant_pool_tag();
316 } else if (strcmp(_token, ARRAY_TAG) == 0) {
317 _token = _line + offset;
318 parse_array_dimension_tag();
319 } else if (strcmp(_token, CLASS_REFLECTION_DATA_TAG) == 0) {
320 _token = _line + offset;
321 parse_class_reflection_data_tag();
322 } else if (strcmp(_token, DYNAMIC_PROXY_TAG) == 0) {
323 _token = _line + offset;
324 parse_dynamic_proxy_tag();
325 } else if (strcmp(_token, LOADER_NEGATIVE_CACHE_TAG) == 0) {
326 _token = _line + offset;
327 parse_loader_negative_cache_tag();
328 } else {
329 error("Invalid @ tag at the beginning of line \"%s\" line #%zu", _token, lineno());
330 }
331 }
332
333 void ClassListParser::skip_whitespaces() {
334 while (*_token == ' ' || *_token == '\t') {
335 _token ++;
336 }
337 }
338
339 void ClassListParser::skip_non_whitespaces() {
340 while (*_token && *_token != ' ' && *_token != '\t') {
341 _token ++;
342 }
343 }
344
345 void ClassListParser::parse_int(int* value) {
346 skip_whitespaces();
347 if (sscanf(_token, "%i", value) == 1) {
404 void ClassListParser::print_specified_interfaces() {
405 const int n = _interfaces->length();
406 jio_fprintf(defaultStream::error_stream(), "Currently specified interfaces[%d] = {\n", n);
407 for (int i=0; i<n; i++) {
408 InstanceKlass* k = lookup_class_by_id(_interfaces->at(i));
409 jio_fprintf(defaultStream::error_stream(), " %4d = %s\n", _interfaces->at(i), k->name()->as_klass_external_name());
410 }
411 jio_fprintf(defaultStream::error_stream(), "}\n");
412 }
413
414 void ClassListParser::print_actual_interfaces(InstanceKlass* ik) {
415 int n = ik->local_interfaces()->length();
416 jio_fprintf(defaultStream::error_stream(), "Actual interfaces[%d] = {\n", n);
417 for (int i = 0; i < n; i++) {
418 InstanceKlass* e = ik->local_interfaces()->at(i);
419 jio_fprintf(defaultStream::error_stream(), " %s\n", e->name()->as_klass_external_name());
420 }
421 jio_fprintf(defaultStream::error_stream(), "}\n");
422 }
423
424 void ClassListParser::print_diagnostic_info(outputStream* st, const char* msg, ...) {
425 va_list ap;
426 va_start(ap, msg);
427 print_diagnostic_info(st, msg, ap);
428 va_end(ap);
429 }
430
431 void ClassListParser::print_diagnostic_info(outputStream* st, const char* msg, va_list ap) {
432 int error_index = pointer_delta_as_int(_token, _line);
433 if (error_index >= _line_len) {
434 error_index = _line_len - 1;
435 }
436 if (error_index < 0) {
437 error_index = 0;
438 }
439
440 jio_fprintf(defaultStream::error_stream(),
441 "An error has occurred while processing class list file %s %zu:%d.\n",
442 _classlist_file, lineno(), (error_index + 1));
443 jio_vfprintf(defaultStream::error_stream(), msg, ap);
444
445 if (_line_len <= 0) {
446 st->print("\n");
447 } else {
448 st->print(":\n");
449 for (int i=0; i<_line_len; i++) {
450 char c = _line[i];
451 if (c == '\0') {
452 st->print("%s", " ");
453 } else {
454 st->print("%c", c);
455 }
456 }
457 st->print("\n");
458 for (int i=0; i<error_index; i++) {
459 st->print("%s", " ");
460 }
461 st->print("^\n");
462 }
463 }
464
465 void ClassListParser::error(const char* msg, ...) {
466 va_list ap;
467 va_start(ap, msg);
468 fileStream fs(defaultStream::error_stream());
469 //TODO: we should write to UL/error instead, but that requires fixing some tests cases.
470 //LogTarget(Error, cds) lt;
471 //LogStream ls(lt);
472 print_diagnostic_info(&fs, msg, ap);
473 va_end(ap);
474 vm_exit_during_initialization("class list format error.", nullptr);
475 }
476
477 void ClassListParser::check_class_name(const char* class_name) {
478 const char* err = nullptr;
479 size_t len = strlen(class_name);
480 if (len > (size_t)Symbol::max_length()) {
481 err = "class name too long";
482 } else {
483 assert(Symbol::max_length() < INT_MAX && len < INT_MAX, "must be");
484 if (!UTF8::is_legal_utf8((const unsigned char*)class_name, (int)len, /*version_leq_47*/false)) {
485 err = "class name is not valid UTF8";
486 }
487 }
488 if (err != nullptr) {
489 jio_fprintf(defaultStream::error_stream(),
490 "An error has occurred while processing class list file %s:%zu %s\n",
491 _classlist_file, lineno(), err);
492 vm_exit_during_initialization("class list format error.", nullptr);
493 }
494 }
495
496 void ClassListParser::constant_pool_resolution_warning(const char* msg, ...) {
497 va_list ap;
498 va_start(ap, msg);
499 LogTarget(Warning, cds, resolve) lt;
500 LogStream ls(lt);
501 print_diagnostic_info(&ls, msg, ap);
502 ls.print("Your classlist may be out of sync with the JDK or the application.");
503 va_end(ap);
504 }
505
506 // This function is used for loading classes for customized class loaders
507 // during archive dumping.
508 InstanceKlass* ClassListParser::load_class_from_source(Symbol* class_name, TRAPS) {
509 #if !(defined(_LP64) && (defined(LINUX) || defined(__APPLE__) || defined(_WINDOWS)))
510 // The only supported platforms are: (1) Linux/64-bit and (2) Solaris/64-bit and
511 // (3) MacOSX/64-bit and (4) Windowss/64-bit
512 // This #if condition should be in sync with the areCustomLoadersSupportedForCDS
513 // method in test/lib/jdk/test/lib/Platform.java.
514 error("AppCDS custom class loaders not supported on this platform");
515 #endif
516
517 if (!is_super_specified()) {
518 error("If source location is specified, super class must be also specified");
519 }
520 if (!is_id_specified()) {
521 error("If source location is specified, id must be also specified");
522 }
523 if (strncmp(_class_name, "java/", 5) == 0) {
524 log_info(cds)("Prohibited package for non-bootstrap classes: %s.class from %s",
525 _class_name, _source);
760 error("Class %s implements the interface %s, but no interface has been specified in the input line",
761 _class_name, interface_name->as_klass_external_name());
762 ShouldNotReachHere();
763 }
764
765 int i;
766 for (i=0; i<n; i++) {
767 InstanceKlass* k = lookup_class_by_id(_interfaces->at(i));
768 if (interface_name == k->name()) {
769 return k;
770 }
771 }
772
773 // interface_name is not specified by the "interfaces:" keyword.
774 print_specified_interfaces();
775 error("The interface %s implemented by class %s does not match any of the specified interface IDs",
776 interface_name->as_klass_external_name(), _class_name);
777 ShouldNotReachHere();
778 return nullptr;
779 }
780
781 InstanceKlass* ClassListParser::find_builtin_class_helper(JavaThread* current, Symbol* class_name_symbol, oop class_loader_oop) {
782 Handle class_loader(current, class_loader_oop);
783 Handle protection_domain;
784 return SystemDictionary::find_instance_klass(current, class_name_symbol, class_loader, protection_domain);
785 }
786
787 InstanceKlass* ClassListParser::find_builtin_class(JavaThread* current, const char* class_name) {
788 TempNewSymbol class_name_symbol = SymbolTable::new_symbol(class_name);
789 InstanceKlass* ik;
790
791 if ( (ik = find_builtin_class_helper(current, class_name_symbol, nullptr)) != nullptr
792 || (ik = find_builtin_class_helper(current, class_name_symbol, SystemDictionary::java_platform_loader())) != nullptr
793 || (ik = find_builtin_class_helper(current, class_name_symbol, SystemDictionary::java_system_loader())) != nullptr) {
794 return ik;
795 } else {
796 return nullptr;
797 }
798 }
799
800 void ClassListParser::parse_array_dimension_tag() {
801 if (parse_lambda_forms_invokers_only()) {
802 return;
803 }
804
805 skip_whitespaces();
806 char* class_name = _token;
807 skip_non_whitespaces();
808 *_token = '\0';
809 _token ++;
810
811 skip_whitespaces();
812 int dim;
813 parse_uint(&dim);
814
815 JavaThread* THREAD = JavaThread::current();
816 InstanceKlass* ik = find_builtin_class(THREAD, class_name);
817 if (ik == nullptr) {
818 _token = class_name;
819 if (strstr(class_name, "/$Proxy") != nullptr ||
820 strstr(class_name, "MethodHandle$Species_") != nullptr) {
821 // ignore -- TODO: we should filter these out in classListWriter.cpp
822 } else {
823 constant_pool_resolution_warning("class %s is not (yet) loaded by one of the built-in loaders", class_name);
824 }
825 return;
826 }
827
828 if (dim > 0) {
829 ik->array_klass(dim, THREAD);
830 if (HAS_PENDING_EXCEPTION) {
831 error("Array klass allocation failed: %s %d", _class_name, dim);
832 }
833 }
834 }
835
836 void ClassListParser::parse_constant_pool_tag() {
837 if (parse_lambda_forms_invokers_only()) {
838 return;
839 }
840
841 JavaThread* THREAD = JavaThread::current();
842 skip_whitespaces();
843 char* class_name = _token;
844 skip_non_whitespaces();
845 *_token = '\0';
846 _token ++;
847
848 InstanceKlass* ik = find_builtin_class(THREAD, class_name);
849 if (ik == nullptr) {
850 _token = class_name;
851 if (strstr(class_name, "/$Proxy") != nullptr ||
852 strstr(class_name, "MethodHandle$Species_") != nullptr) {
853 // ignore -- TODO: we should filter these out in classListWriter.cpp
854 } else {
855 constant_pool_resolution_warning("class %s is not (yet) loaded by one of the built-in loaders", class_name);
856 }
857 return;
858 }
859
860 ResourceMark rm(THREAD);
861 constantPoolHandle cp(THREAD, ik->constants());
862 GrowableArray<bool> preresolve_list(cp->length(), cp->length(), false);
863 bool preresolve_class = false;
864 bool preresolve_fmi = false;
865 bool preresolve_indy = false;
866
867 while (*_token) {
868 int cp_index;
869 skip_whitespaces();
870 parse_uint(&cp_index);
871 if (cp_index < 1 || cp_index >= cp->length()) {
872 constant_pool_resolution_warning("Invalid constant pool index %d", cp_index);
873 return;
874 } else {
875 preresolve_list.at_put(cp_index, true);
876 }
877 constantTag cp_tag = cp->tag_at(cp_index);
878 switch (cp_tag.value()) {
879 case JVM_CONSTANT_UnresolvedClass:
880 preresolve_class = true;
881 break;
882 case JVM_CONSTANT_UnresolvedClassInError:
883 case JVM_CONSTANT_Class:
884 // ignore
885 break;
886 case JVM_CONSTANT_Fieldref:
887 case JVM_CONSTANT_Methodref:
888 case JVM_CONSTANT_InterfaceMethodref:
889 preresolve_fmi = true;
890 break;
891 case JVM_CONSTANT_InvokeDynamic:
892 preresolve_indy = true;
893 break;
894 default:
895 constant_pool_resolution_warning("Unsupported constant pool index %d: %s (type=%d)",
896 cp_index, cp_tag.internal_name(), cp_tag.value());
897 return;
898 }
899 }
900
901 if (preresolve_class) {
902 ClassPrelinker::preresolve_class_cp_entries(THREAD, ik, &preresolve_list);
903 }
904 if (preresolve_fmi) {
905 // FIXME: too coarse; doesn't cover resolution of Class entries
906 // JavaThread::NoJavaCodeMark no_java_code(THREAD); // ensure no clinits are exectued
907 ClassPrelinker::preresolve_field_and_method_cp_entries(THREAD, ik, &preresolve_list);
908 }
909 if (preresolve_indy) {
910 ClassPrelinker::preresolve_indy_cp_entries(THREAD, ik, &preresolve_list);
911 }
912 }
913
914 void ClassListParser::parse_class_reflection_data_tag() {
915 if (parse_lambda_forms_invokers_only()) {
916 return;
917 }
918
919 JavaThread* THREAD = JavaThread::current();
920 skip_whitespaces();
921 char* class_name = _token;
922 skip_non_whitespaces();
923 *_token = '\0';
924 _token ++;
925
926 InstanceKlass* ik = find_builtin_class(THREAD, class_name);
927 if (ik == nullptr) {
928 _token = class_name;
929 if (strstr(class_name, "/$Proxy") != nullptr ||
930 strstr(class_name, "MethodHandle$Species_") != nullptr) {
931 // ignore -- TODO: we should filter these out in classListWriter.cpp
932 } else {
933 warning("%s: class not found: %s", CLASS_REFLECTION_DATA_TAG, class_name);
934 }
935 return;
936 }
937
938 ResourceMark rm(THREAD);
939
940 int rd_flags = _unspecified;
941 while (*_token) {
942 skip_whitespaces();
943 if (rd_flags != _unspecified) {
944 error("rd_flags specified twice");
945 return;
946 }
947 parse_uint(&rd_flags);
948 }
949 if (rd_flags == _unspecified) {
950 error("no rd_flags specified");
951 return;
952 }
953
954 if (ArchiveReflectionData) {
955 ClassPrelinker::generate_reflection_data(THREAD, ik, rd_flags);
956 }
957 }
958
959 oop ClassListParser::loader_from_type(const char* loader_type) {
960 oop loader;
961 if (!ArchiveUtils::builtin_loader_from_type(loader_type, &loader)) {
962 error("Unknown loader %s", loader_type);
963 }
964 return loader;
965 }
966
967 void ClassListParser::parse_dynamic_proxy_tag() {
968 if (parse_lambda_forms_invokers_only()) {
969 return;
970 }
971
972 skip_whitespaces();
973 char* loader_type = _token;
974 skip_non_whitespaces();
975 *_token = '\0';
976 _token ++;
977
978 skip_whitespaces();
979 char* proxy_name_str = _token;
980 skip_non_whitespaces();
981 *_token = '\0';
982 _token ++;
983
984 skip_whitespaces();
985 int access_flags;
986 parse_uint(&access_flags);
987
988 skip_whitespaces();
989 int num_intfs;
990 parse_uint(&num_intfs);
991
992 JavaThread* THREAD = JavaThread::current();
993 Handle loader(THREAD, loader_from_type(loader_type));
994 Handle proxy_name(THREAD, java_lang_String::create_oop_from_str(proxy_name_str, THREAD));
995 if (HAS_PENDING_EXCEPTION) {
996 error("Out of memory");
997 }
998
999 objArrayHandle interfaces(THREAD, oopFactory::new_objArray(vmClasses::Class_klass(), num_intfs, THREAD));
1000 if (HAS_PENDING_EXCEPTION) {
1001 error("Out of memory");
1002 }
1003
1004 for (int i = 0; i < num_intfs; i++) {
1005 skip_whitespaces();
1006 char* intf_name = _token;
1007 skip_non_whitespaces();
1008 *_token = '\0';
1009 _token ++;
1010
1011 InstanceKlass* ik = find_builtin_class(THREAD, intf_name);
1012 if (ik != nullptr) {
1013 interfaces()->obj_at_put(i, ik->java_mirror());
1014 } else {
1015 error("Unknown class %s", intf_name);
1016 }
1017 }
1018
1019 if (strncmp("jdk.proxy", proxy_name_str, 9) != 0) {
1020 return;
1021 }
1022
1023 ClassPrelinker::define_dynamic_proxy_class(loader, proxy_name, interfaces, access_flags, THREAD);
1024 if (HAS_PENDING_EXCEPTION) {
1025 PENDING_EXCEPTION->print_on(tty);
1026 error("defineProxyClassForCDS failed");
1027 }
1028 }
1029
1030 void ClassListParser::parse_loader_negative_cache_tag() {
1031 skip_whitespaces();
1032 char* loader_type = _token;
1033 skip_non_whitespaces();
1034 *_token = '\0';
1035 _token ++;
1036
1037 oop loader;
1038 Klass* loader_klass;
1039 if (!strcmp(loader_type, "app")) {
1040 loader = SystemDictionary::java_system_loader();
1041 loader_klass = vmClasses::jdk_internal_loader_ClassLoaders_AppClassLoader_klass();
1042 } else if (!strcmp(loader_type, "platform")) {
1043 loader = SystemDictionary::java_platform_loader();
1044 loader_klass = vmClasses::jdk_internal_loader_ClassLoaders_PlatformClassLoader_klass();
1045 } else {
1046 warning("%s: unrecognized loader type %s is ignored", LOADER_NEGATIVE_CACHE_TAG, loader_type);
1047 return;
1048 }
1049
1050 char* contents = _token;
1051 skip_non_whitespaces();
1052 *_token = '\0';
1053 _token ++;
1054
1055 if (ArchiveLoaderLookupCache) {
1056 TempNewSymbol method = SymbolTable::new_symbol("generateNegativeLookupCache");
1057 TempNewSymbol signature = SymbolTable::new_symbol("(Ljava/lang/String;)V");
1058
1059 EXCEPTION_MARK;
1060 HandleMark hm(THREAD);
1061 JavaCallArguments args(Handle(THREAD, loader));
1062 Handle contents_h = java_lang_String::create_from_str(contents, THREAD);
1063 args.push_oop(contents_h);
1064 JavaValue result(T_VOID);
1065 JavaCalls::call_virtual(&result,
1066 loader_klass,
1067 method,
1068 signature,
1069 &args, THREAD);
1070 if (HAS_PENDING_EXCEPTION) {
1071 Handle exc_handle(THREAD, PENDING_EXCEPTION);
1072 CLEAR_PENDING_EXCEPTION;
1073
1074 log_warning(cds)("Exception during BuiltinClassLoader::generateNegativeLookupCache() call for %s loader", loader_type);
1075 LogStreamHandle(Debug, cds) log;
1076 if (log.is_enabled()) {
1077 java_lang_Throwable::print_stack_trace(exc_handle, &log);
1078 }
1079 }
1080 }
1081 }
|