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