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/archiveUtils.hpp"
28 #include "cds/classListParser.hpp"
29 #include "cds/lambdaFormInvokers.hpp"
30 #include "cds/lambdaProxyClassDictionary.hpp"
31 #include "cds/metaspaceShared.hpp"
32 #include "cds/unregisteredClasses.hpp"
33 #include "classfile/classLoaderExt.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/bytecodeStream.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 "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::CONSTANT_POOL_TAG = "@cp";
60 const char* ClassListParser::LAMBDA_FORM_TAG = "@lambda-form-invoker";
61 const char* ClassListParser::LAMBDA_PROXY_TAG = "@lambda-proxy";
62
63 volatile Thread* ClassListParser::_parsing_thread = nullptr;
64 ClassListParser* ClassListParser::_instance = nullptr;
65
66 ClassListParser::ClassListParser(const char* file, ParseMode parse_mode) :
67 _classlist_file(file),
68 _id2klass_table(INITIAL_TABLE_SIZE, MAX_TABLE_SIZE),
69 _file_input(do_open(file), /* need_close=*/true),
70 _input_stream(&_file_input),
71 _parse_mode(parse_mode) {
72 aot_log_info(aot)("Parsing %s%s", file,
73 parse_lambda_forms_invokers_only() ? " (lambda form invokers only)" : "");
74 if (!_file_input.is_open()) {
75 char reason[JVM_MAXPATHLEN];
76 os::lasterror(reason, JVM_MAXPATHLEN);
77 vm_exit_during_initialization(err_msg("Loading %s %s failed",
78 FLAG_IS_DEFAULT(AOTConfiguration) ?
79 "classlist" : "AOTConfiguration file",
80 file),
81 reason);
303 if (strcmp(_token, LAMBDA_PROXY_TAG) == 0) {
304 _indy_items->clear();
305 split_tokens_by_whitespace(offset, _indy_items);
306 if (_indy_items->length() < 2) {
307 error("Line with @ tag has too few items \"%s\" line #%zu", _token, lineno());
308 }
309 if (!parse_lambda_forms_invokers_only()) {
310 _class_name = _indy_items->at(0);
311 check_class_name(_class_name);
312 TempNewSymbol class_name_symbol = SymbolTable::new_symbol(_class_name);
313 if (_indy_items->length() > 0) {
314 // The current line is "@lambda-proxy class_name". Load the proxy class.
315 resolve_indy(THREAD, class_name_symbol);
316 }
317 }
318 } else if (strcmp(_token, LAMBDA_FORM_TAG) == 0) {
319 LambdaFormInvokers::append(os::strdup((const char*)(_line + offset), mtInternal));
320 } else if (strcmp(_token, CONSTANT_POOL_TAG) == 0) {
321 _token = _line + offset;
322 parse_constant_pool_tag();
323 } else {
324 error("Invalid @ tag at the beginning of line \"%s\" line #%zu", _token, lineno());
325 }
326 }
327
328 void ClassListParser::skip_whitespaces() {
329 while (*_token == ' ' || *_token == '\t') {
330 _token ++;
331 }
332 }
333
334 void ClassListParser::skip_non_whitespaces() {
335 while (*_token && *_token != ' ' && *_token != '\t') {
336 _token ++;
337 }
338 }
339
340 void ClassListParser::parse_int(int* value) {
341 skip_whitespaces();
342 if (sscanf(_token, "%i", value) == 1) {
795 }
796
797 InstanceKlass* ClassListParser::find_builtin_class_helper(JavaThread* current, Symbol* class_name_symbol, oop class_loader_oop) {
798 Handle class_loader(current, class_loader_oop);
799 return SystemDictionary::find_instance_klass(current, class_name_symbol, class_loader);
800 }
801
802 InstanceKlass* ClassListParser::find_builtin_class(JavaThread* current, const char* class_name) {
803 TempNewSymbol class_name_symbol = SymbolTable::new_symbol(class_name);
804 InstanceKlass* ik;
805
806 if ( (ik = find_builtin_class_helper(current, class_name_symbol, nullptr)) != nullptr
807 || (ik = find_builtin_class_helper(current, class_name_symbol, SystemDictionary::java_platform_loader())) != nullptr
808 || (ik = find_builtin_class_helper(current, class_name_symbol, SystemDictionary::java_system_loader())) != nullptr) {
809 return ik;
810 } else {
811 return nullptr;
812 }
813 }
814
815 void ClassListParser::parse_constant_pool_tag() {
816 if (parse_lambda_forms_invokers_only()) {
817 return;
818 }
819
820 JavaThread* THREAD = JavaThread::current();
821 skip_whitespaces();
822 char* class_name = _token;
823 skip_non_whitespaces();
824 *_token = '\0';
825 _token ++;
826
827 InstanceKlass* ik = find_builtin_class(THREAD, class_name);
828 if (ik == nullptr) {
829 _token = class_name;
830 if (strstr(class_name, "/$Proxy") != nullptr ||
831 strstr(class_name, "MethodHandle$Species_") != nullptr) {
832 // ignore -- TODO: we should filter these out in classListWriter.cpp
833 } else {
834 constant_pool_resolution_warning("class %s is not (yet) loaded by one of the built-in loaders", class_name);
872 break;
873 default:
874 constant_pool_resolution_warning("Unsupported constant pool index %d: %s (type=%d)",
875 cp_index, cp_tag.internal_name(), cp_tag.value());
876 return;
877 }
878 }
879
880 if (SystemDictionaryShared::should_be_excluded(ik)) {
881 if (log_is_enabled(Warning, aot, resolve)) {
882 ResourceMark rm;
883 log_warning(aot, resolve)("Cannot aot-resolve constants for %s because it is excluded", ik->external_name());
884 }
885 return;
886 }
887
888 if (preresolve_class) {
889 AOTConstantPoolResolver::preresolve_class_cp_entries(THREAD, ik, &preresolve_list);
890 }
891 if (preresolve_fmi) {
892 AOTConstantPoolResolver::preresolve_field_and_method_cp_entries(THREAD, ik, &preresolve_list);
893 }
894 if (preresolve_indy) {
895 AOTConstantPoolResolver::preresolve_indy_cp_entries(THREAD, ik, &preresolve_list);
896 }
897 }
|
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/archiveUtils.hpp"
28 #include "cds/cdsConfig.hpp"
29 #include "cds/classListParser.hpp"
30 #include "cds/lambdaFormInvokers.hpp"
31 #include "cds/lambdaProxyClassDictionary.hpp"
32 #include "cds/metaspaceShared.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/atomic.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);
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) {
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);
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
|