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) {
762
763 InstanceKlass* ClassListParser::find_builtin_class_helper(JavaThread* current, Symbol* class_name_symbol, oop class_loader_oop) {
764 Handle class_loader(current, class_loader_oop);
765 Handle protection_domain;
766 return SystemDictionary::find_instance_klass(current, class_name_symbol, class_loader, protection_domain);
767 }
768
769 InstanceKlass* ClassListParser::find_builtin_class(JavaThread* current, const char* class_name) {
770 TempNewSymbol class_name_symbol = SymbolTable::new_symbol(class_name);
771 InstanceKlass* ik;
772
773 if ( (ik = find_builtin_class_helper(current, class_name_symbol, nullptr)) != nullptr
774 || (ik = find_builtin_class_helper(current, class_name_symbol, SystemDictionary::java_platform_loader())) != nullptr
775 || (ik = find_builtin_class_helper(current, class_name_symbol, SystemDictionary::java_system_loader())) != nullptr) {
776 return ik;
777 } else {
778 return nullptr;
779 }
780 }
781
782 void ClassListParser::parse_constant_pool_tag() {
783 if (parse_lambda_forms_invokers_only()) {
784 return;
785 }
786
787 JavaThread* THREAD = JavaThread::current();
788 skip_whitespaces();
789 char* class_name = _token;
790 skip_non_whitespaces();
791 *_token = '\0';
792 _token ++;
793
794 InstanceKlass* ik = find_builtin_class(THREAD, class_name);
795 if (ik == nullptr) {
796 _token = class_name;
797 if (strstr(class_name, "/$Proxy") != nullptr ||
798 strstr(class_name, "MethodHandle$Species_") != nullptr) {
799 // ignore -- TODO: we should filter these out in classListWriter.cpp
800 } else {
801 constant_pool_resolution_warning("class %s is not (yet) loaded by one of the built-in loaders", class_name);
817 if (cp_index < 1 || cp_index >= cp->length()) {
818 constant_pool_resolution_warning("Invalid constant pool index %d", cp_index);
819 return;
820 } else {
821 preresolve_list.at_put(cp_index, true);
822 }
823 constantTag cp_tag = cp->tag_at(cp_index);
824 switch (cp_tag.value()) {
825 case JVM_CONSTANT_UnresolvedClass:
826 preresolve_class = true;
827 break;
828 case JVM_CONSTANT_UnresolvedClassInError:
829 case JVM_CONSTANT_Class:
830 // ignore
831 break;
832 case JVM_CONSTANT_Fieldref:
833 case JVM_CONSTANT_Methodref:
834 case JVM_CONSTANT_InterfaceMethodref:
835 preresolve_fmi = true;
836 break;
837 break;
838 default:
839 constant_pool_resolution_warning("Unsupported constant pool index %d: %s (type=%d)",
840 cp_index, cp_tag.internal_name(), cp_tag.value());
841 return;
842 }
843 }
844
845 if (preresolve_class) {
846 ClassPrelinker::preresolve_class_cp_entries(THREAD, ik, &preresolve_list);
847 }
848 if (preresolve_fmi) {
849 ClassPrelinker::preresolve_field_and_method_cp_entries(THREAD, ik, &preresolve_list);
850 }
851 }
852
|
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/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");
301 if (strcmp(_token, LAMBDA_PROXY_TAG) == 0) {
302 _indy_items->clear();
303 split_tokens_by_whitespace(offset, _indy_items);
304 if (_indy_items->length() < 2) {
305 error("Line with @ tag has too few items \"%s\" line #%zu", _token, lineno());
306 }
307 if (!parse_lambda_forms_invokers_only()) {
308 _class_name = _indy_items->at(0);
309 check_class_name(_class_name);
310 TempNewSymbol class_name_symbol = SymbolTable::new_symbol(_class_name);
311 if (_indy_items->length() > 0) {
312 // The current line is "@lambda-proxy class_name". Load the proxy class.
313 resolve_indy(THREAD, class_name_symbol);
314 }
315 }
316 } else if (strcmp(_token, LAMBDA_FORM_TAG) == 0) {
317 LambdaFormInvokers::append(os::strdup((const char*)(_line + offset), mtInternal));
318 } else if (strcmp(_token, CONSTANT_POOL_TAG) == 0) {
319 _token = _line + offset;
320 parse_constant_pool_tag();
321 } else if (strcmp(_token, ARRAY_TAG) == 0) {
322 _token = _line + offset;
323 parse_array_dimension_tag();
324 } else if (strcmp(_token, CLASS_REFLECTION_DATA_TAG) == 0) {
325 _token = _line + offset;
326 parse_class_reflection_data_tag();
327 } else if (strcmp(_token, DYNAMIC_PROXY_TAG) == 0) {
328 _token = _line + offset;
329 parse_dynamic_proxy_tag();
330 } else if (strcmp(_token, LOADER_NEGATIVE_CACHE_TAG) == 0) {
331 _token = _line + offset;
332 parse_loader_negative_cache_tag();
333 } else {
334 error("Invalid @ tag at the beginning of line \"%s\" line #%zu", _token, lineno());
335 }
336 }
337
338 void ClassListParser::skip_whitespaces() {
339 while (*_token == ' ' || *_token == '\t') {
340 _token ++;
341 }
342 }
343
344 void ClassListParser::skip_non_whitespaces() {
345 while (*_token && *_token != ' ' && *_token != '\t') {
346 _token ++;
347 }
348 }
349
350 void ClassListParser::parse_int(int* value) {
351 skip_whitespaces();
352 if (sscanf(_token, "%i", value) == 1) {
785
786 InstanceKlass* ClassListParser::find_builtin_class_helper(JavaThread* current, Symbol* class_name_symbol, oop class_loader_oop) {
787 Handle class_loader(current, class_loader_oop);
788 Handle protection_domain;
789 return SystemDictionary::find_instance_klass(current, class_name_symbol, class_loader, protection_domain);
790 }
791
792 InstanceKlass* ClassListParser::find_builtin_class(JavaThread* current, const char* class_name) {
793 TempNewSymbol class_name_symbol = SymbolTable::new_symbol(class_name);
794 InstanceKlass* ik;
795
796 if ( (ik = find_builtin_class_helper(current, class_name_symbol, nullptr)) != nullptr
797 || (ik = find_builtin_class_helper(current, class_name_symbol, SystemDictionary::java_platform_loader())) != nullptr
798 || (ik = find_builtin_class_helper(current, class_name_symbol, SystemDictionary::java_system_loader())) != nullptr) {
799 return ik;
800 } else {
801 return nullptr;
802 }
803 }
804
805 void ClassListParser::parse_array_dimension_tag() {
806 if (parse_lambda_forms_invokers_only()) {
807 return;
808 }
809
810 skip_whitespaces();
811 char* class_name = _token;
812 skip_non_whitespaces();
813 *_token = '\0';
814 _token ++;
815
816 skip_whitespaces();
817 int dim;
818 parse_uint(&dim);
819
820 JavaThread* THREAD = JavaThread::current();
821 InstanceKlass* ik = find_builtin_class(THREAD, class_name);
822 if (ik == nullptr) {
823 _token = class_name;
824 if (strstr(class_name, "/$Proxy") != nullptr ||
825 strstr(class_name, "MethodHandle$Species_") != nullptr) {
826 // ignore -- TODO: we should filter these out in classListWriter.cpp
827 } else {
828 constant_pool_resolution_warning("class %s is not (yet) loaded by one of the built-in loaders", class_name);
829 }
830 return;
831 }
832
833 if (dim > 0) {
834 ik->array_klass(dim, THREAD);
835 if (HAS_PENDING_EXCEPTION) {
836 error("Array klass allocation failed: %s %d", _class_name, dim);
837 }
838 }
839 }
840
841 void ClassListParser::parse_constant_pool_tag() {
842 if (parse_lambda_forms_invokers_only()) {
843 return;
844 }
845
846 JavaThread* THREAD = JavaThread::current();
847 skip_whitespaces();
848 char* class_name = _token;
849 skip_non_whitespaces();
850 *_token = '\0';
851 _token ++;
852
853 InstanceKlass* ik = find_builtin_class(THREAD, class_name);
854 if (ik == nullptr) {
855 _token = class_name;
856 if (strstr(class_name, "/$Proxy") != nullptr ||
857 strstr(class_name, "MethodHandle$Species_") != nullptr) {
858 // ignore -- TODO: we should filter these out in classListWriter.cpp
859 } else {
860 constant_pool_resolution_warning("class %s is not (yet) loaded by one of the built-in loaders", class_name);
876 if (cp_index < 1 || cp_index >= cp->length()) {
877 constant_pool_resolution_warning("Invalid constant pool index %d", cp_index);
878 return;
879 } else {
880 preresolve_list.at_put(cp_index, true);
881 }
882 constantTag cp_tag = cp->tag_at(cp_index);
883 switch (cp_tag.value()) {
884 case JVM_CONSTANT_UnresolvedClass:
885 preresolve_class = true;
886 break;
887 case JVM_CONSTANT_UnresolvedClassInError:
888 case JVM_CONSTANT_Class:
889 // ignore
890 break;
891 case JVM_CONSTANT_Fieldref:
892 case JVM_CONSTANT_Methodref:
893 case JVM_CONSTANT_InterfaceMethodref:
894 preresolve_fmi = true;
895 break;
896 case JVM_CONSTANT_InvokeDynamic:
897 preresolve_indy = true;
898 break;
899 default:
900 constant_pool_resolution_warning("Unsupported constant pool index %d: %s (type=%d)",
901 cp_index, cp_tag.internal_name(), cp_tag.value());
902 return;
903 }
904 }
905
906 if (preresolve_class) {
907 AOTConstantPoolResolver::preresolve_class_cp_entries(THREAD, ik, &preresolve_list);
908 }
909 if (preresolve_fmi) {
910 // FIXME: too coarse; doesn't cover resolution of Class entries
911 // JavaThread::NoJavaCodeMark no_java_code(THREAD); // ensure no clinits are exectued
912 AOTConstantPoolResolver::preresolve_field_and_method_cp_entries(THREAD, ik, &preresolve_list);
913 }
914 if (preresolve_indy) {
915 AOTConstantPoolResolver::preresolve_indy_cp_entries(THREAD, ik, &preresolve_list);
916 }
917 }
918
919 void ClassListParser::parse_class_reflection_data_tag() {
920 if (parse_lambda_forms_invokers_only()) {
921 return;
922 }
923
924 JavaThread* THREAD = JavaThread::current();
925 skip_whitespaces();
926 char* class_name = _token;
927 skip_non_whitespaces();
928 *_token = '\0';
929 _token ++;
930
931 InstanceKlass* ik = find_builtin_class(THREAD, class_name);
932 if (ik == nullptr) {
933 _token = class_name;
934 if (strstr(class_name, "/$Proxy") != nullptr ||
935 strstr(class_name, "MethodHandle$Species_") != nullptr) {
936 // ignore -- TODO: we should filter these out in classListWriter.cpp
937 } else {
938 warning("%s: class not found: %s", CLASS_REFLECTION_DATA_TAG, class_name);
939 }
940 return;
941 }
942
943 ResourceMark rm(THREAD);
944
945 int rd_flags = _unspecified;
946 while (*_token) {
947 skip_whitespaces();
948 if (rd_flags != _unspecified) {
949 error("rd_flags specified twice");
950 return;
951 }
952 parse_uint(&rd_flags);
953 }
954 if (rd_flags == _unspecified) {
955 error("no rd_flags specified");
956 return;
957 }
958
959 if (CDSConfig::is_dumping_reflection_data()) {
960 AOTConstantPoolResolver::generate_reflection_data(THREAD, ik, rd_flags);
961 }
962 }
963
964 oop ClassListParser::loader_from_type(const char* loader_type) {
965 oop loader;
966 if (!ArchiveUtils::builtin_loader_from_type(loader_type, &loader)) {
967 error("Unknown loader %s", loader_type);
968 }
969 return loader;
970 }
971
972 void ClassListParser::parse_dynamic_proxy_tag() {
973 if (parse_lambda_forms_invokers_only()) {
974 return;
975 }
976
977 skip_whitespaces();
978 char* loader_type = _token;
979 skip_non_whitespaces();
980 *_token = '\0';
981 _token ++;
982
983 skip_whitespaces();
984 char* proxy_name_str = _token;
985 skip_non_whitespaces();
986 *_token = '\0';
987 _token ++;
988
989 skip_whitespaces();
990 int access_flags;
991 parse_uint(&access_flags);
992
993 skip_whitespaces();
994 int num_intfs;
995 parse_uint(&num_intfs);
996
997 JavaThread* THREAD = JavaThread::current();
998 Handle loader(THREAD, loader_from_type(loader_type));
999 Handle proxy_name(THREAD, java_lang_String::create_oop_from_str(proxy_name_str, THREAD));
1000 if (HAS_PENDING_EXCEPTION) {
1001 error("Out of memory");
1002 }
1003
1004 objArrayHandle interfaces(THREAD, oopFactory::new_objArray(vmClasses::Class_klass(), num_intfs, THREAD));
1005 if (HAS_PENDING_EXCEPTION) {
1006 error("Out of memory");
1007 }
1008
1009 for (int i = 0; i < num_intfs; i++) {
1010 skip_whitespaces();
1011 char* intf_name = _token;
1012 skip_non_whitespaces();
1013 *_token = '\0';
1014 _token ++;
1015
1016 InstanceKlass* ik = find_builtin_class(THREAD, intf_name);
1017 if (ik != nullptr) {
1018 interfaces()->obj_at_put(i, ik->java_mirror());
1019 } else {
1020 error("Unknown class %s", intf_name);
1021 }
1022 }
1023
1024 if (strncmp("jdk.proxy", proxy_name_str, 9) != 0) {
1025 return;
1026 }
1027
1028 AOTConstantPoolResolver::define_dynamic_proxy_class(loader, proxy_name, interfaces, access_flags, THREAD);
1029 if (HAS_PENDING_EXCEPTION) {
1030 PENDING_EXCEPTION->print_on(tty);
1031 error("defineProxyClassForCDS failed");
1032 }
1033 }
1034
1035 void ClassListParser::parse_loader_negative_cache_tag() {
1036 skip_whitespaces();
1037 char* loader_type = _token;
1038 skip_non_whitespaces();
1039 *_token = '\0';
1040 _token ++;
1041
1042 oop loader;
1043 Klass* loader_klass;
1044 if (!strcmp(loader_type, "app")) {
1045 loader = SystemDictionary::java_system_loader();
1046 loader_klass = vmClasses::jdk_internal_loader_ClassLoaders_AppClassLoader_klass();
1047 } else if (!strcmp(loader_type, "platform")) {
1048 loader = SystemDictionary::java_platform_loader();
1049 loader_klass = vmClasses::jdk_internal_loader_ClassLoaders_PlatformClassLoader_klass();
1050 } else {
1051 warning("%s: unrecognized loader type %s is ignored", LOADER_NEGATIVE_CACHE_TAG, loader_type);
1052 return;
1053 }
1054
1055 char* contents = _token;
1056 skip_non_whitespaces();
1057 *_token = '\0';
1058 _token ++;
1059
1060 if (ArchiveLoaderLookupCache) {
1061 TempNewSymbol method = SymbolTable::new_symbol("generateNegativeLookupCache");
1062 TempNewSymbol signature = SymbolTable::new_symbol("(Ljava/lang/String;)V");
1063
1064 EXCEPTION_MARK;
1065 HandleMark hm(THREAD);
1066 JavaCallArguments args(Handle(THREAD, loader));
1067 Handle contents_h = java_lang_String::create_from_str(contents, THREAD);
1068 args.push_oop(contents_h);
1069 JavaValue result(T_VOID);
1070 JavaCalls::call_virtual(&result,
1071 loader_klass,
1072 method,
1073 signature,
1074 &args, THREAD);
1075 if (HAS_PENDING_EXCEPTION) {
1076 Handle exc_handle(THREAD, PENDING_EXCEPTION);
1077 CLEAR_PENDING_EXCEPTION;
1078
1079 log_warning(cds)("Exception during BuiltinClassLoader::generateNegativeLookupCache() call for %s loader", loader_type);
1080 LogStreamHandle(Debug, cds) log;
1081 if (log.is_enabled()) {
1082 java_lang_Throwable::print_stack_trace(exc_handle, &log);
1083 }
1084 }
1085 }
1086 }
|