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