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/classListParser.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/globals_extension.hpp"
50 #include "runtime/handles.inline.hpp"
51 #include "runtime/java.hpp"
52 #include "runtime/javaCalls.hpp"
53 #include "utilities/defaultStream.hpp"
54 #include "utilities/macros.hpp"
55 #include "utilities/utf8.hpp"
56
57 const char* ClassListParser::CONSTANT_POOL_TAG = "@cp";
58 const char* ClassListParser::LAMBDA_FORM_TAG = "@lambda-form-invoker";
59 const char* ClassListParser::LAMBDA_PROXY_TAG = "@lambda-proxy";
60
61 volatile Thread* ClassListParser::_parsing_thread = nullptr;
62 ClassListParser* ClassListParser::_instance = nullptr;
63
64 ClassListParser::ClassListParser(const char* file, ParseMode parse_mode) :
65 _classlist_file(file),
66 _id2klass_table(INITIAL_TABLE_SIZE, MAX_TABLE_SIZE),
67 _file_input(do_open(file), /* need_close=*/true),
68 _input_stream(&_file_input),
69 _parse_mode(parse_mode) {
70 log_info(cds)("Parsing %s%s", file,
71 parse_lambda_forms_invokers_only() ? " (lambda form invokers only)" : "");
72 if (!_file_input.is_open()) {
73 char reason[JVM_MAXPATHLEN];
74 os::lasterror(reason, JVM_MAXPATHLEN);
75 vm_exit_during_initialization(err_msg("Loading %s %s failed",
76 FLAG_IS_DEFAULT(AOTConfiguration) ?
77 "classlist" : "AOTConfiguration file",
78 file),
79 reason);
295 if (strcmp(_token, LAMBDA_PROXY_TAG) == 0) {
296 _indy_items->clear();
297 split_tokens_by_whitespace(offset, _indy_items);
298 if (_indy_items->length() < 2) {
299 error("Line with @ tag has too few items \"%s\" line #%zu", _token, lineno());
300 }
301 if (!parse_lambda_forms_invokers_only()) {
302 _class_name = _indy_items->at(0);
303 check_class_name(_class_name);
304 TempNewSymbol class_name_symbol = SymbolTable::new_symbol(_class_name);
305 if (_indy_items->length() > 0) {
306 // The current line is "@lambda-proxy class_name". Load the proxy class.
307 resolve_indy(THREAD, class_name_symbol);
308 }
309 }
310 } else if (strcmp(_token, LAMBDA_FORM_TAG) == 0) {
311 LambdaFormInvokers::append(os::strdup((const char*)(_line + offset), mtInternal));
312 } else if (strcmp(_token, CONSTANT_POOL_TAG) == 0) {
313 _token = _line + offset;
314 parse_constant_pool_tag();
315 } else {
316 error("Invalid @ tag at the beginning of line \"%s\" line #%zu", _token, lineno());
317 }
318 }
319
320 void ClassListParser::skip_whitespaces() {
321 while (*_token == ' ' || *_token == '\t') {
322 _token ++;
323 }
324 }
325
326 void ClassListParser::skip_non_whitespaces() {
327 while (*_token && *_token != ' ' && *_token != '\t') {
328 _token ++;
329 }
330 }
331
332 void ClassListParser::parse_int(int* value) {
333 skip_whitespaces();
334 if (sscanf(_token, "%i", value) == 1) {
781
782 InstanceKlass* ClassListParser::find_builtin_class_helper(JavaThread* current, Symbol* class_name_symbol, oop class_loader_oop) {
783 Handle class_loader(current, class_loader_oop);
784 Handle protection_domain;
785 return SystemDictionary::find_instance_klass(current, class_name_symbol, class_loader, protection_domain);
786 }
787
788 InstanceKlass* ClassListParser::find_builtin_class(JavaThread* current, const char* class_name) {
789 TempNewSymbol class_name_symbol = SymbolTable::new_symbol(class_name);
790 InstanceKlass* ik;
791
792 if ( (ik = find_builtin_class_helper(current, class_name_symbol, nullptr)) != nullptr
793 || (ik = find_builtin_class_helper(current, class_name_symbol, SystemDictionary::java_platform_loader())) != nullptr
794 || (ik = find_builtin_class_helper(current, class_name_symbol, SystemDictionary::java_system_loader())) != nullptr) {
795 return ik;
796 } else {
797 return nullptr;
798 }
799 }
800
801 void ClassListParser::parse_constant_pool_tag() {
802 if (parse_lambda_forms_invokers_only()) {
803 return;
804 }
805
806 JavaThread* THREAD = JavaThread::current();
807 skip_whitespaces();
808 char* class_name = _token;
809 skip_non_whitespaces();
810 *_token = '\0';
811 _token ++;
812
813 InstanceKlass* ik = find_builtin_class(THREAD, class_name);
814 if (ik == nullptr) {
815 _token = class_name;
816 if (strstr(class_name, "/$Proxy") != nullptr ||
817 strstr(class_name, "MethodHandle$Species_") != nullptr) {
818 // ignore -- TODO: we should filter these out in classListWriter.cpp
819 } else {
820 constant_pool_resolution_warning("class %s is not (yet) loaded by one of the built-in loaders", class_name);
850 break;
851 case JVM_CONSTANT_Fieldref:
852 case JVM_CONSTANT_Methodref:
853 case JVM_CONSTANT_InterfaceMethodref:
854 preresolve_fmi = true;
855 break;
856 case JVM_CONSTANT_InvokeDynamic:
857 preresolve_indy = true;
858 break;
859 default:
860 constant_pool_resolution_warning("Unsupported constant pool index %d: %s (type=%d)",
861 cp_index, cp_tag.internal_name(), cp_tag.value());
862 return;
863 }
864 }
865
866 if (preresolve_class) {
867 AOTConstantPoolResolver::preresolve_class_cp_entries(THREAD, ik, &preresolve_list);
868 }
869 if (preresolve_fmi) {
870 AOTConstantPoolResolver::preresolve_field_and_method_cp_entries(THREAD, ik, &preresolve_list);
871 }
872 if (preresolve_indy) {
873 AOTConstantPoolResolver::preresolve_indy_cp_entries(THREAD, ik, &preresolve_list);
874 }
875 }
|
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);
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) {
800
801 InstanceKlass* ClassListParser::find_builtin_class_helper(JavaThread* current, Symbol* class_name_symbol, oop class_loader_oop) {
802 Handle class_loader(current, class_loader_oop);
803 Handle protection_domain;
804 return SystemDictionary::find_instance_klass(current, class_name_symbol, class_loader, protection_domain);
805 }
806
807 InstanceKlass* ClassListParser::find_builtin_class(JavaThread* current, const char* class_name) {
808 TempNewSymbol class_name_symbol = SymbolTable::new_symbol(class_name);
809 InstanceKlass* ik;
810
811 if ( (ik = find_builtin_class_helper(current, class_name_symbol, nullptr)) != nullptr
812 || (ik = find_builtin_class_helper(current, class_name_symbol, SystemDictionary::java_platform_loader())) != nullptr
813 || (ik = find_builtin_class_helper(current, class_name_symbol, SystemDictionary::java_system_loader())) != nullptr) {
814 return ik;
815 } else {
816 return nullptr;
817 }
818 }
819
820 void ClassListParser::parse_array_dimension_tag() {
821 if (parse_lambda_forms_invokers_only()) {
822 return;
823 }
824
825 skip_whitespaces();
826 char* class_name = _token;
827 skip_non_whitespaces();
828 *_token = '\0';
829 _token ++;
830
831 skip_whitespaces();
832 int dim;
833 parse_uint(&dim);
834
835 JavaThread* THREAD = JavaThread::current();
836 InstanceKlass* ik = find_builtin_class(THREAD, class_name);
837 if (ik == nullptr) {
838 _token = class_name;
839 if (strstr(class_name, "/$Proxy") != nullptr ||
840 strstr(class_name, "MethodHandle$Species_") != nullptr) {
841 // ignore -- TODO: we should filter these out in classListWriter.cpp
842 } else {
843 constant_pool_resolution_warning("class %s is not (yet) loaded by one of the built-in loaders", class_name);
844 }
845 return;
846 }
847
848 if (dim > 0) {
849 ik->array_klass(dim, THREAD);
850 if (HAS_PENDING_EXCEPTION) {
851 error("Array klass allocation failed: %s %d", _class_name, dim);
852 }
853 }
854 }
855
856 void ClassListParser::parse_constant_pool_tag() {
857 if (parse_lambda_forms_invokers_only()) {
858 return;
859 }
860
861 JavaThread* THREAD = JavaThread::current();
862 skip_whitespaces();
863 char* class_name = _token;
864 skip_non_whitespaces();
865 *_token = '\0';
866 _token ++;
867
868 InstanceKlass* ik = find_builtin_class(THREAD, class_name);
869 if (ik == nullptr) {
870 _token = class_name;
871 if (strstr(class_name, "/$Proxy") != nullptr ||
872 strstr(class_name, "MethodHandle$Species_") != nullptr) {
873 // ignore -- TODO: we should filter these out in classListWriter.cpp
874 } else {
875 constant_pool_resolution_warning("class %s is not (yet) loaded by one of the built-in loaders", class_name);
905 break;
906 case JVM_CONSTANT_Fieldref:
907 case JVM_CONSTANT_Methodref:
908 case JVM_CONSTANT_InterfaceMethodref:
909 preresolve_fmi = true;
910 break;
911 case JVM_CONSTANT_InvokeDynamic:
912 preresolve_indy = true;
913 break;
914 default:
915 constant_pool_resolution_warning("Unsupported constant pool index %d: %s (type=%d)",
916 cp_index, cp_tag.internal_name(), cp_tag.value());
917 return;
918 }
919 }
920
921 if (preresolve_class) {
922 AOTConstantPoolResolver::preresolve_class_cp_entries(THREAD, ik, &preresolve_list);
923 }
924 if (preresolve_fmi) {
925 // FIXME: too coarse; doesn't cover resolution of Class entries
926 // JavaThread::NoJavaCodeMark no_java_code(THREAD); // ensure no clinits are exectued
927 AOTConstantPoolResolver::preresolve_field_and_method_cp_entries(THREAD, ik, &preresolve_list);
928 }
929 if (preresolve_indy) {
930 AOTConstantPoolResolver::preresolve_indy_cp_entries(THREAD, ik, &preresolve_list);
931 }
932 }
933
934 void ClassListParser::parse_class_reflection_data_tag() {
935 if (parse_lambda_forms_invokers_only()) {
936 return;
937 }
938
939 JavaThread* THREAD = JavaThread::current();
940 skip_whitespaces();
941 char* class_name = _token;
942 skip_non_whitespaces();
943 *_token = '\0';
944 _token ++;
945
946 InstanceKlass* ik = find_builtin_class(THREAD, class_name);
947 if (ik == nullptr) {
948 _token = class_name;
949 if (strstr(class_name, "/$Proxy") != nullptr ||
950 strstr(class_name, "MethodHandle$Species_") != nullptr) {
951 // ignore -- TODO: we should filter these out in classListWriter.cpp
952 } else {
953 warning("%s: class not found: %s", CLASS_REFLECTION_DATA_TAG, class_name);
954 }
955 return;
956 }
957
958 ResourceMark rm(THREAD);
959
960 int rd_flags = _unspecified;
961 while (*_token) {
962 skip_whitespaces();
963 if (rd_flags != _unspecified) {
964 error("rd_flags specified twice");
965 return;
966 }
967 parse_uint(&rd_flags);
968 }
969 if (rd_flags == _unspecified) {
970 error("no rd_flags specified");
971 return;
972 }
973
974 if (CDSConfig::is_dumping_reflection_data()) {
975 AOTConstantPoolResolver::generate_reflection_data(THREAD, ik, rd_flags);
976 }
977 }
978
979 oop ClassListParser::loader_from_type(const char* loader_type) {
980 oop loader;
981 if (!ArchiveUtils::builtin_loader_from_type(loader_type, &loader)) {
982 error("Unknown loader %s", loader_type);
983 }
984 return loader;
985 }
986
987 void ClassListParser::parse_dynamic_proxy_tag() {
988 if (parse_lambda_forms_invokers_only()) {
989 return;
990 }
991
992 skip_whitespaces();
993 char* loader_type = _token;
994 skip_non_whitespaces();
995 *_token = '\0';
996 _token ++;
997
998 skip_whitespaces();
999 char* proxy_name_str = _token;
1000 skip_non_whitespaces();
1001 *_token = '\0';
1002 _token ++;
1003
1004 skip_whitespaces();
1005 int access_flags;
1006 parse_uint(&access_flags);
1007
1008 skip_whitespaces();
1009 int num_intfs;
1010 parse_uint(&num_intfs);
1011
1012 JavaThread* THREAD = JavaThread::current();
1013 Handle loader(THREAD, loader_from_type(loader_type));
1014 Handle proxy_name(THREAD, java_lang_String::create_oop_from_str(proxy_name_str, THREAD));
1015 if (HAS_PENDING_EXCEPTION) {
1016 error("Out of memory");
1017 }
1018
1019 objArrayHandle interfaces(THREAD, oopFactory::new_objArray(vmClasses::Class_klass(), num_intfs, THREAD));
1020 if (HAS_PENDING_EXCEPTION) {
1021 error("Out of memory");
1022 }
1023
1024 for (int i = 0; i < num_intfs; i++) {
1025 skip_whitespaces();
1026 char* intf_name = _token;
1027 skip_non_whitespaces();
1028 *_token = '\0';
1029 _token ++;
1030
1031 InstanceKlass* ik = find_builtin_class(THREAD, intf_name);
1032 if (ik != nullptr) {
1033 interfaces()->obj_at_put(i, ik->java_mirror());
1034 } else {
1035 error("Unknown class %s", intf_name);
1036 }
1037 }
1038
1039 if (strncmp("jdk.proxy", proxy_name_str, 9) != 0) {
1040 return;
1041 }
1042
1043 AOTConstantPoolResolver::define_dynamic_proxy_class(loader, proxy_name, interfaces, access_flags, THREAD);
1044 if (HAS_PENDING_EXCEPTION) {
1045 PENDING_EXCEPTION->print_on(tty);
1046 error("defineProxyClassForCDS failed");
1047 }
1048 }
1049
1050 void ClassListParser::parse_loader_negative_cache_tag() {
1051 skip_whitespaces();
1052 char* loader_type = _token;
1053 skip_non_whitespaces();
1054 *_token = '\0';
1055 _token ++;
1056
1057 oop loader;
1058 Klass* loader_klass;
1059 if (!strcmp(loader_type, "app")) {
1060 loader = SystemDictionary::java_system_loader();
1061 loader_klass = vmClasses::jdk_internal_loader_ClassLoaders_AppClassLoader_klass();
1062 } else if (!strcmp(loader_type, "platform")) {
1063 loader = SystemDictionary::java_platform_loader();
1064 loader_klass = vmClasses::jdk_internal_loader_ClassLoaders_PlatformClassLoader_klass();
1065 } else {
1066 warning("%s: unrecognized loader type %s is ignored", LOADER_NEGATIVE_CACHE_TAG, loader_type);
1067 return;
1068 }
1069
1070 char* contents = _token;
1071 skip_non_whitespaces();
1072 *_token = '\0';
1073 _token ++;
1074
1075 if (ArchiveLoaderLookupCache) {
1076 TempNewSymbol method = SymbolTable::new_symbol("generateNegativeLookupCache");
1077 TempNewSymbol signature = SymbolTable::new_symbol("(Ljava/lang/String;)V");
1078
1079 EXCEPTION_MARK;
1080 HandleMark hm(THREAD);
1081 JavaCallArguments args(Handle(THREAD, loader));
1082 Handle contents_h = java_lang_String::create_from_str(contents, THREAD);
1083 args.push_oop(contents_h);
1084 JavaValue result(T_VOID);
1085 JavaCalls::call_virtual(&result,
1086 loader_klass,
1087 method,
1088 signature,
1089 &args, THREAD);
1090 if (HAS_PENDING_EXCEPTION) {
1091 Handle exc_handle(THREAD, PENDING_EXCEPTION);
1092 CLEAR_PENDING_EXCEPTION;
1093
1094 log_warning(cds)("Exception during BuiltinClassLoader::generateNegativeLookupCache() call for %s loader", loader_type);
1095 LogStreamHandle(Debug, cds) log;
1096 if (log.is_enabled()) {
1097 java_lang_Throwable::print_stack_trace(exc_handle, &log);
1098 }
1099 }
1100 }
1101 }
1102
|