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