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 "precompiled.hpp"
26 #include "cds/archiveUtils.hpp"
27 #include "cds/classListParser.hpp"
28 #include "cds/classPrelinker.hpp"
29 #include "cds/lambdaFormInvokers.hpp"
30 #include "cds/metaspaceShared.hpp"
31 #include "cds/unregisteredClasses.hpp"
32 #include "classfile/classLoaderExt.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/bytecodeStream.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/resourceArea.hpp"
47 #include "oops/constantPool.inline.hpp"
48 #include "runtime/atomic.hpp"
49 #include "runtime/handles.inline.hpp"
50 #include "runtime/java.hpp"
51 #include "runtime/javaCalls.hpp"
52 #include "utilities/defaultStream.hpp"
53 #include "utilities/macros.hpp"
54 #include "utilities/utf8.hpp"
55
56 const char* ClassListParser::CONSTANT_POOL_TAG = "@cp";
57 const char* ClassListParser::LAMBDA_FORM_TAG = "@lambda-form-invoker";
58 const char* ClassListParser::LAMBDA_PROXY_TAG = "@lambda-proxy";
59
60 volatile Thread* ClassListParser::_parsing_thread = nullptr;
61 ClassListParser* ClassListParser::_instance = nullptr;
62
63 ClassListParser::ClassListParser(const char* file, ParseMode parse_mode) :
64 _classlist_file(file),
65 _id2klass_table(INITIAL_TABLE_SIZE, MAX_TABLE_SIZE),
66 _file_input(do_open(file), /* need_close=*/true),
67 _input_stream(&_file_input),
68 _parse_mode(parse_mode) {
69 log_info(cds)("Parsing %s%s", file,
70 parse_lambda_forms_invokers_only() ? " (lambda form invokers only)" : "");
71 if (!_file_input.is_open()) {
72 char errmsg[JVM_MAXPATHLEN];
73 os::lasterror(errmsg, JVM_MAXPATHLEN);
74 vm_exit_during_initialization("Loading classlist failed", errmsg);
75 }
76 _token = _line = nullptr;
77 _interfaces = new (mtClass) GrowableArray<int>(10, mtClass);
78 _indy_items = new (mtClass) GrowableArray<const char*>(9, mtClass);
79
80 // _instance should only be accessed by the thread that created _instance.
81 assert(_instance == nullptr, "must be singleton");
82 _instance = this;
83 Atomic::store(&_parsing_thread, Thread::current());
84 }
85
86 FILE* ClassListParser::do_open(const char* file) {
87 // Use os::open() because neither fopen() nor os::fopen()
88 // can handle long path name on Windows. (See JDK-8216184)
89 int fd = os::open(file, O_RDONLY, S_IREAD);
90 FILE* fp = nullptr;
91 if (fd != -1) {
92 // Obtain a FILE* from the file descriptor so that _input_stream
93 // can be used in ClassListParser::parse()
94 fp = os::fdopen(fd, "r");
290 if (strcmp(_token, LAMBDA_PROXY_TAG) == 0) {
291 _indy_items->clear();
292 split_tokens_by_whitespace(offset, _indy_items);
293 if (_indy_items->length() < 2) {
294 error("Line with @ tag has too few items \"%s\" line #%zu", _token, lineno());
295 }
296 if (!parse_lambda_forms_invokers_only()) {
297 _class_name = _indy_items->at(0);
298 check_class_name(_class_name);
299 TempNewSymbol class_name_symbol = SymbolTable::new_symbol(_class_name);
300 if (_indy_items->length() > 0) {
301 // The current line is "@lambda-proxy class_name". Load the proxy class.
302 resolve_indy(THREAD, class_name_symbol);
303 }
304 }
305 } else if (strcmp(_token, LAMBDA_FORM_TAG) == 0) {
306 LambdaFormInvokers::append(os::strdup((const char*)(_line + offset), mtInternal));
307 } else if (strcmp(_token, CONSTANT_POOL_TAG) == 0) {
308 _token = _line + offset;
309 parse_constant_pool_tag();
310 } else {
311 error("Invalid @ tag at the beginning of line \"%s\" line #%zu", _token, lineno());
312 }
313 }
314
315 void ClassListParser::skip_whitespaces() {
316 while (*_token == ' ' || *_token == '\t') {
317 _token ++;
318 }
319 }
320
321 void ClassListParser::skip_non_whitespaces() {
322 while (*_token && *_token != ' ' && *_token != '\t') {
323 _token ++;
324 }
325 }
326
327 void ClassListParser::parse_int(int* value) {
328 skip_whitespaces();
329 if (sscanf(_token, "%i", value) == 1) {
764
765 InstanceKlass* ClassListParser::find_builtin_class_helper(JavaThread* current, Symbol* class_name_symbol, oop class_loader_oop) {
766 Handle class_loader(current, class_loader_oop);
767 Handle protection_domain;
768 return SystemDictionary::find_instance_klass(current, class_name_symbol, class_loader, protection_domain);
769 }
770
771 InstanceKlass* ClassListParser::find_builtin_class(JavaThread* current, const char* class_name) {
772 TempNewSymbol class_name_symbol = SymbolTable::new_symbol(class_name);
773 InstanceKlass* ik;
774
775 if ( (ik = find_builtin_class_helper(current, class_name_symbol, nullptr)) != nullptr
776 || (ik = find_builtin_class_helper(current, class_name_symbol, SystemDictionary::java_platform_loader())) != nullptr
777 || (ik = find_builtin_class_helper(current, class_name_symbol, SystemDictionary::java_system_loader())) != nullptr) {
778 return ik;
779 } else {
780 return nullptr;
781 }
782 }
783
784 void ClassListParser::parse_constant_pool_tag() {
785 if (parse_lambda_forms_invokers_only()) {
786 return;
787 }
788
789 JavaThread* THREAD = JavaThread::current();
790 skip_whitespaces();
791 char* class_name = _token;
792 skip_non_whitespaces();
793 *_token = '\0';
794 _token ++;
795
796 InstanceKlass* ik = find_builtin_class(THREAD, class_name);
797 if (ik == nullptr) {
798 _token = class_name;
799 if (strstr(class_name, "/$Proxy") != nullptr ||
800 strstr(class_name, "MethodHandle$Species_") != nullptr) {
801 // ignore -- TODO: we should filter these out in classListWriter.cpp
802 } else {
803 constant_pool_resolution_warning("class %s is not (yet) loaded by one of the built-in loaders", class_name);
819 if (cp_index < 1 || cp_index >= cp->length()) {
820 constant_pool_resolution_warning("Invalid constant pool index %d", cp_index);
821 return;
822 } else {
823 preresolve_list.at_put(cp_index, true);
824 }
825 constantTag cp_tag = cp->tag_at(cp_index);
826 switch (cp_tag.value()) {
827 case JVM_CONSTANT_UnresolvedClass:
828 preresolve_class = true;
829 break;
830 case JVM_CONSTANT_UnresolvedClassInError:
831 case JVM_CONSTANT_Class:
832 // ignore
833 break;
834 case JVM_CONSTANT_Fieldref:
835 case JVM_CONSTANT_Methodref:
836 case JVM_CONSTANT_InterfaceMethodref:
837 preresolve_fmi = true;
838 break;
839 break;
840 default:
841 constant_pool_resolution_warning("Unsupported constant pool index %d: %s (type=%d)",
842 cp_index, cp_tag.internal_name(), cp_tag.value());
843 return;
844 }
845 }
846
847 if (preresolve_class) {
848 ClassPrelinker::preresolve_class_cp_entries(THREAD, ik, &preresolve_list);
849 }
850 if (preresolve_fmi) {
851 ClassPrelinker::preresolve_field_and_method_cp_entries(THREAD, ik, &preresolve_list);
852 }
853 }
|
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 "precompiled.hpp"
26 #include "cds/aotConstantPoolResolver.hpp"
27 #include "cds/archiveUtils.hpp"
28 #include "cds/cdsConfig.hpp"
29 #include "cds/classListParser.hpp"
30 #include "cds/lambdaFormInvokers.hpp"
31 #include "cds/metaspaceShared.hpp"
32 #include "cds/unregisteredClasses.hpp"
33 #include "classfile/classLoader.hpp"
34 #include "classfile/javaClasses.inline.hpp"
35 #include "classfile/symbolTable.hpp"
36 #include "classfile/systemDictionary.hpp"
37 #include "classfile/systemDictionaryShared.hpp"
38 #include "classfile/vmClasses.hpp"
39 #include "classfile/vmSymbols.hpp"
40 #include "interpreter/bytecode.hpp"
41 #include "interpreter/interpreterRuntime.hpp"
42 #include "interpreter/linkResolver.hpp"
43 #include "jimage.hpp"
44 #include "jvm.h"
45 #include "logging/log.hpp"
46 #include "logging/logTag.hpp"
47 #include "memory/oopFactory.hpp"
48 #include "memory/resourceArea.hpp"
49 #include "oops/constantPool.inline.hpp"
50 #include "oops/cpCache.inline.hpp"
51 #include "runtime/atomic.hpp"
52 #include "runtime/globals_extension.hpp"
53 #include "runtime/handles.inline.hpp"
54 #include "runtime/java.hpp"
55 #include "runtime/javaCalls.hpp"
56 #include "utilities/defaultStream.hpp"
57 #include "utilities/macros.hpp"
58 #include "utilities/utf8.hpp"
59
60 const char* ClassListParser::CLASS_REFLECTION_DATA_TAG = "@class-reflection-data";
61 const char* ClassListParser::CONSTANT_POOL_TAG = "@cp";
62 const char* ClassListParser::DYNAMIC_PROXY_TAG = "@dynamic-proxy";
63 const char* ClassListParser::LAMBDA_FORM_TAG = "@lambda-form-invoker";
64 const char* ClassListParser::LAMBDA_PROXY_TAG = "@lambda-proxy";
65 const char* ClassListParser::LOADER_NEGATIVE_CACHE_TAG = "@loader-negative-cache";
66 const char* ClassListParser::ARRAY_TAG = "@array";
67
68 volatile Thread* ClassListParser::_parsing_thread = nullptr;
69 ClassListParser* ClassListParser::_instance = nullptr;
70
71 ClassListParser::ClassListParser(const char* file, ParseMode parse_mode) :
72 _classlist_file(file),
73 _id2klass_table(INITIAL_TABLE_SIZE, MAX_TABLE_SIZE),
74 _file_input(do_open(file), /* need_close=*/true),
75 _input_stream(&_file_input),
76 _parse_mode(parse_mode) {
77 log_info(cds)("Parsing %s%s", file,
78 parse_lambda_forms_invokers_only() ? " (lambda form invokers only)" : "");
79 if (!_file_input.is_open()) {
80 char reason[JVM_MAXPATHLEN];
81 os::lasterror(reason, JVM_MAXPATHLEN);
82 vm_exit_during_initialization(err_msg("Loading %s %s failed",
83 FLAG_IS_DEFAULT(AOTConfiguration) ?
84 "classlist" : "AOTConfiguration file",
85 file),
86 reason);
87 }
88 _token = _line = nullptr;
89 _interfaces = new (mtClass) GrowableArray<int>(10, mtClass);
90 _indy_items = new (mtClass) GrowableArray<const char*>(9, mtClass);
91
92 // _instance should only be accessed by the thread that created _instance.
93 assert(_instance == nullptr, "must be singleton");
94 _instance = this;
95 Atomic::store(&_parsing_thread, Thread::current());
96 }
97
98 FILE* ClassListParser::do_open(const char* file) {
99 // Use os::open() because neither fopen() nor os::fopen()
100 // can handle long path name on Windows. (See JDK-8216184)
101 int fd = os::open(file, O_RDONLY, S_IREAD);
102 FILE* fp = nullptr;
103 if (fd != -1) {
104 // Obtain a FILE* from the file descriptor so that _input_stream
105 // can be used in ClassListParser::parse()
106 fp = os::fdopen(fd, "r");
302 if (strcmp(_token, LAMBDA_PROXY_TAG) == 0) {
303 _indy_items->clear();
304 split_tokens_by_whitespace(offset, _indy_items);
305 if (_indy_items->length() < 2) {
306 error("Line with @ tag has too few items \"%s\" line #%zu", _token, lineno());
307 }
308 if (!parse_lambda_forms_invokers_only()) {
309 _class_name = _indy_items->at(0);
310 check_class_name(_class_name);
311 TempNewSymbol class_name_symbol = SymbolTable::new_symbol(_class_name);
312 if (_indy_items->length() > 0) {
313 // The current line is "@lambda-proxy class_name". Load the proxy class.
314 resolve_indy(THREAD, class_name_symbol);
315 }
316 }
317 } else if (strcmp(_token, LAMBDA_FORM_TAG) == 0) {
318 LambdaFormInvokers::append(os::strdup((const char*)(_line + offset), mtInternal));
319 } else if (strcmp(_token, CONSTANT_POOL_TAG) == 0) {
320 _token = _line + offset;
321 parse_constant_pool_tag();
322 } else if (strcmp(_token, ARRAY_TAG) == 0) {
323 _token = _line + offset;
324 parse_array_dimension_tag();
325 } else if (strcmp(_token, CLASS_REFLECTION_DATA_TAG) == 0) {
326 _token = _line + offset;
327 parse_class_reflection_data_tag();
328 } else if (strcmp(_token, DYNAMIC_PROXY_TAG) == 0) {
329 _token = _line + offset;
330 parse_dynamic_proxy_tag();
331 } else if (strcmp(_token, LOADER_NEGATIVE_CACHE_TAG) == 0) {
332 _token = _line + offset;
333 parse_loader_negative_cache_tag();
334 } else {
335 error("Invalid @ tag at the beginning of line \"%s\" line #%zu", _token, lineno());
336 }
337 }
338
339 void ClassListParser::skip_whitespaces() {
340 while (*_token == ' ' || *_token == '\t') {
341 _token ++;
342 }
343 }
344
345 void ClassListParser::skip_non_whitespaces() {
346 while (*_token && *_token != ' ' && *_token != '\t') {
347 _token ++;
348 }
349 }
350
351 void ClassListParser::parse_int(int* value) {
352 skip_whitespaces();
353 if (sscanf(_token, "%i", value) == 1) {
788
789 InstanceKlass* ClassListParser::find_builtin_class_helper(JavaThread* current, Symbol* class_name_symbol, oop class_loader_oop) {
790 Handle class_loader(current, class_loader_oop);
791 Handle protection_domain;
792 return SystemDictionary::find_instance_klass(current, class_name_symbol, class_loader, protection_domain);
793 }
794
795 InstanceKlass* ClassListParser::find_builtin_class(JavaThread* current, const char* class_name) {
796 TempNewSymbol class_name_symbol = SymbolTable::new_symbol(class_name);
797 InstanceKlass* ik;
798
799 if ( (ik = find_builtin_class_helper(current, class_name_symbol, nullptr)) != nullptr
800 || (ik = find_builtin_class_helper(current, class_name_symbol, SystemDictionary::java_platform_loader())) != nullptr
801 || (ik = find_builtin_class_helper(current, class_name_symbol, SystemDictionary::java_system_loader())) != nullptr) {
802 return ik;
803 } else {
804 return nullptr;
805 }
806 }
807
808 void ClassListParser::parse_array_dimension_tag() {
809 if (parse_lambda_forms_invokers_only()) {
810 return;
811 }
812
813 skip_whitespaces();
814 char* class_name = _token;
815 skip_non_whitespaces();
816 *_token = '\0';
817 _token ++;
818
819 skip_whitespaces();
820 int dim;
821 parse_uint(&dim);
822
823 JavaThread* THREAD = JavaThread::current();
824 InstanceKlass* ik = find_builtin_class(THREAD, class_name);
825 if (ik == nullptr) {
826 _token = class_name;
827 if (strstr(class_name, "/$Proxy") != nullptr ||
828 strstr(class_name, "MethodHandle$Species_") != nullptr) {
829 // ignore -- TODO: we should filter these out in classListWriter.cpp
830 } else {
831 constant_pool_resolution_warning("class %s is not (yet) loaded by one of the built-in loaders", class_name);
832 }
833 return;
834 }
835
836 if (dim > 0) {
837 ik->array_klass(dim, THREAD);
838 if (HAS_PENDING_EXCEPTION) {
839 error("Array klass allocation failed: %s %d", _class_name, dim);
840 }
841 }
842 }
843
844 void ClassListParser::parse_constant_pool_tag() {
845 if (parse_lambda_forms_invokers_only()) {
846 return;
847 }
848
849 JavaThread* THREAD = JavaThread::current();
850 skip_whitespaces();
851 char* class_name = _token;
852 skip_non_whitespaces();
853 *_token = '\0';
854 _token ++;
855
856 InstanceKlass* ik = find_builtin_class(THREAD, class_name);
857 if (ik == nullptr) {
858 _token = class_name;
859 if (strstr(class_name, "/$Proxy") != nullptr ||
860 strstr(class_name, "MethodHandle$Species_") != nullptr) {
861 // ignore -- TODO: we should filter these out in classListWriter.cpp
862 } else {
863 constant_pool_resolution_warning("class %s is not (yet) loaded by one of the built-in loaders", class_name);
879 if (cp_index < 1 || cp_index >= cp->length()) {
880 constant_pool_resolution_warning("Invalid constant pool index %d", cp_index);
881 return;
882 } else {
883 preresolve_list.at_put(cp_index, true);
884 }
885 constantTag cp_tag = cp->tag_at(cp_index);
886 switch (cp_tag.value()) {
887 case JVM_CONSTANT_UnresolvedClass:
888 preresolve_class = true;
889 break;
890 case JVM_CONSTANT_UnresolvedClassInError:
891 case JVM_CONSTANT_Class:
892 // ignore
893 break;
894 case JVM_CONSTANT_Fieldref:
895 case JVM_CONSTANT_Methodref:
896 case JVM_CONSTANT_InterfaceMethodref:
897 preresolve_fmi = true;
898 break;
899 case JVM_CONSTANT_InvokeDynamic:
900 preresolve_indy = true;
901 break;
902 default:
903 constant_pool_resolution_warning("Unsupported constant pool index %d: %s (type=%d)",
904 cp_index, cp_tag.internal_name(), cp_tag.value());
905 return;
906 }
907 }
908
909 if (preresolve_class) {
910 AOTConstantPoolResolver::preresolve_class_cp_entries(THREAD, ik, &preresolve_list);
911 }
912 if (preresolve_fmi) {
913 // FIXME: too coarse; doesn't cover resolution of Class entries
914 // JavaThread::NoJavaCodeMark no_java_code(THREAD); // ensure no clinits are exectued
915 AOTConstantPoolResolver::preresolve_field_and_method_cp_entries(THREAD, ik, &preresolve_list);
916 }
917 if (preresolve_indy) {
918 AOTConstantPoolResolver::preresolve_indy_cp_entries(THREAD, ik, &preresolve_list);
919 }
920 }
921
922 void ClassListParser::parse_class_reflection_data_tag() {
923 if (parse_lambda_forms_invokers_only()) {
924 return;
925 }
926
927 JavaThread* THREAD = JavaThread::current();
928 skip_whitespaces();
929 char* class_name = _token;
930 skip_non_whitespaces();
931 *_token = '\0';
932 _token ++;
933
934 InstanceKlass* ik = find_builtin_class(THREAD, class_name);
935 if (ik == nullptr) {
936 _token = class_name;
937 if (strstr(class_name, "/$Proxy") != nullptr ||
938 strstr(class_name, "MethodHandle$Species_") != nullptr) {
939 // ignore -- TODO: we should filter these out in classListWriter.cpp
940 } else {
941 warning("%s: class not found: %s", CLASS_REFLECTION_DATA_TAG, class_name);
942 }
943 return;
944 }
945
946 ResourceMark rm(THREAD);
947
948 int rd_flags = _unspecified;
949 while (*_token) {
950 skip_whitespaces();
951 if (rd_flags != _unspecified) {
952 error("rd_flags specified twice");
953 return;
954 }
955 parse_uint(&rd_flags);
956 }
957 if (rd_flags == _unspecified) {
958 error("no rd_flags specified");
959 return;
960 }
961
962 if (CDSConfig::is_dumping_reflection_data()) {
963 AOTConstantPoolResolver::generate_reflection_data(THREAD, ik, rd_flags);
964 }
965 }
966
967 oop ClassListParser::loader_from_type(const char* loader_type) {
968 oop loader;
969 if (!ArchiveUtils::builtin_loader_from_type(loader_type, &loader)) {
970 error("Unknown loader %s", loader_type);
971 }
972 return loader;
973 }
974
975 void ClassListParser::parse_dynamic_proxy_tag() {
976 if (parse_lambda_forms_invokers_only()) {
977 return;
978 }
979
980 skip_whitespaces();
981 char* loader_type = _token;
982 skip_non_whitespaces();
983 *_token = '\0';
984 _token ++;
985
986 skip_whitespaces();
987 char* proxy_name_str = _token;
988 skip_non_whitespaces();
989 *_token = '\0';
990 _token ++;
991
992 skip_whitespaces();
993 int access_flags;
994 parse_uint(&access_flags);
995
996 skip_whitespaces();
997 int num_intfs;
998 parse_uint(&num_intfs);
999
1000 JavaThread* THREAD = JavaThread::current();
1001 Handle loader(THREAD, loader_from_type(loader_type));
1002 Handle proxy_name(THREAD, java_lang_String::create_oop_from_str(proxy_name_str, THREAD));
1003 if (HAS_PENDING_EXCEPTION) {
1004 error("Out of memory");
1005 }
1006
1007 objArrayHandle interfaces(THREAD, oopFactory::new_objArray(vmClasses::Class_klass(), num_intfs, THREAD));
1008 if (HAS_PENDING_EXCEPTION) {
1009 error("Out of memory");
1010 }
1011
1012 for (int i = 0; i < num_intfs; i++) {
1013 skip_whitespaces();
1014 char* intf_name = _token;
1015 skip_non_whitespaces();
1016 *_token = '\0';
1017 _token ++;
1018
1019 InstanceKlass* ik = find_builtin_class(THREAD, intf_name);
1020 if (ik != nullptr) {
1021 interfaces()->obj_at_put(i, ik->java_mirror());
1022 } else {
1023 error("Unknown class %s", intf_name);
1024 }
1025 }
1026
1027 if (strncmp("jdk.proxy", proxy_name_str, 9) != 0) {
1028 return;
1029 }
1030
1031 AOTConstantPoolResolver::define_dynamic_proxy_class(loader, proxy_name, interfaces, access_flags, THREAD);
1032 if (HAS_PENDING_EXCEPTION) {
1033 PENDING_EXCEPTION->print_on(tty);
1034 error("defineProxyClassForCDS failed");
1035 }
1036 }
1037
1038 void ClassListParser::parse_loader_negative_cache_tag() {
1039 skip_whitespaces();
1040 char* loader_type = _token;
1041 skip_non_whitespaces();
1042 *_token = '\0';
1043 _token ++;
1044
1045 oop loader;
1046 Klass* loader_klass;
1047 if (!strcmp(loader_type, "app")) {
1048 loader = SystemDictionary::java_system_loader();
1049 loader_klass = vmClasses::jdk_internal_loader_ClassLoaders_AppClassLoader_klass();
1050 } else if (!strcmp(loader_type, "platform")) {
1051 loader = SystemDictionary::java_platform_loader();
1052 loader_klass = vmClasses::jdk_internal_loader_ClassLoaders_PlatformClassLoader_klass();
1053 } else {
1054 warning("%s: unrecognized loader type %s is ignored", LOADER_NEGATIVE_CACHE_TAG, loader_type);
1055 return;
1056 }
1057
1058 char* contents = _token;
1059 skip_non_whitespaces();
1060 *_token = '\0';
1061 _token ++;
1062
1063 if (ArchiveLoaderLookupCache) {
1064 TempNewSymbol method = SymbolTable::new_symbol("generateNegativeLookupCache");
1065 TempNewSymbol signature = SymbolTable::new_symbol("(Ljava/lang/String;)V");
1066
1067 EXCEPTION_MARK;
1068 HandleMark hm(THREAD);
1069 JavaCallArguments args(Handle(THREAD, loader));
1070 Handle contents_h = java_lang_String::create_from_str(contents, THREAD);
1071 args.push_oop(contents_h);
1072 JavaValue result(T_VOID);
1073 JavaCalls::call_virtual(&result,
1074 loader_klass,
1075 method,
1076 signature,
1077 &args, THREAD);
1078 if (HAS_PENDING_EXCEPTION) {
1079 Handle exc_handle(THREAD, PENDING_EXCEPTION);
1080 CLEAR_PENDING_EXCEPTION;
1081
1082 log_warning(cds)("Exception during BuiltinClassLoader::generateNegativeLookupCache() call for %s loader", loader_type);
1083 LogStreamHandle(Debug, cds) log;
1084 if (log.is_enabled()) {
1085 java_lang_Throwable::print_stack_trace(exc_handle, &log);
1086 }
1087 }
1088 }
1089 }
1090
|