610 return methodHandle(THREAD, result); |
610 return methodHandle(THREAD, result); |
611 } |
611 } |
612 } |
612 } |
613 |
613 |
614 if (code == Bytecodes::_invokeinterface) { |
614 if (code == Bytecodes::_invokeinterface) { |
615 return resolve_interface_method(link_info, true, THREAD); |
615 return resolve_interface_method(link_info, code, THREAD); |
616 } else if (code == Bytecodes::_invokevirtual) { |
616 } else if (code == Bytecodes::_invokevirtual) { |
617 return resolve_method(link_info, /*require_methodref*/true, THREAD); |
617 return resolve_method(link_info, /*require_methodref*/true, THREAD); |
618 } else if (!resolved_klass->is_interface()) { |
618 } else if (!resolved_klass->is_interface()) { |
619 return resolve_method(link_info, /*require_methodref*/false, THREAD); |
619 return resolve_method(link_info, /*require_methodref*/false, THREAD); |
620 } else { |
620 } else { |
621 bool nostatics = (code == Bytecodes::_invokestatic) ? false : true; |
621 return resolve_interface_method(link_info, code, THREAD); |
622 return resolve_interface_method(link_info, nostatics, THREAD); |
|
623 } |
622 } |
624 } |
623 } |
625 |
624 |
626 // Check and print a loader constraint violation message for method or interface method |
625 // Check and print a loader constraint violation message for method or interface method |
627 void LinkResolver::check_method_loader_constraints(const LinkInfo& link_info, |
626 void LinkResolver::check_method_loader_constraints(const LinkInfo& link_info, |
775 } |
774 } |
776 st->cr(); |
775 st->cr(); |
777 #endif // PRODUCT |
776 #endif // PRODUCT |
778 } |
777 } |
779 |
778 |
780 methodHandle LinkResolver::resolve_interface_method(const LinkInfo& link_info, |
779 // Do linktime resolution of a method in the interface within the context of the specied bytecode. |
781 bool nostatics, TRAPS) { |
780 methodHandle LinkResolver::resolve_interface_method(const LinkInfo& link_info, Bytecodes::Code code, TRAPS) { |
782 |
781 |
783 KlassHandle resolved_klass = link_info.resolved_klass(); |
782 KlassHandle resolved_klass = link_info.resolved_klass(); |
784 |
783 |
785 // check if klass is interface |
784 // check if klass is interface |
786 if (!resolved_klass->is_interface()) { |
785 if (!resolved_klass->is_interface()) { |
822 CHECK_NULL); |
821 CHECK_NULL); |
823 |
822 |
824 check_method_loader_constraints(link_info, resolved_method, "interface method", CHECK_NULL); |
823 check_method_loader_constraints(link_info, resolved_method, "interface method", CHECK_NULL); |
825 } |
824 } |
826 |
825 |
827 if (nostatics && resolved_method->is_static()) { |
826 if (code != Bytecodes::_invokestatic && resolved_method->is_static()) { |
828 ResourceMark rm(THREAD); |
827 ResourceMark rm(THREAD); |
829 char buf[200]; |
828 char buf[200]; |
830 jio_snprintf(buf, sizeof(buf), "Expected instance not static method %s", |
829 jio_snprintf(buf, sizeof(buf), "Expected instance not static method %s", |
831 Method::name_and_sig_as_C_string(resolved_klass(), |
830 Method::name_and_sig_as_C_string(resolved_klass(), |
832 resolved_method->name(), resolved_method->signature())); |
831 resolved_method->name(), resolved_method->signature())); |
833 THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); |
832 THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); |
|
833 } |
|
834 |
|
835 if (code == Bytecodes::_invokeinterface && resolved_method->is_private()) { |
|
836 ResourceMark rm(THREAD); |
|
837 char buf[200]; |
|
838 |
|
839 KlassHandle current_klass = link_info.current_klass(); |
|
840 jio_snprintf(buf, sizeof(buf), "private interface method requires invokespecial, not invokeinterface: method %s, caller-class:%s", |
|
841 Method::name_and_sig_as_C_string(resolved_klass(), |
|
842 resolved_method->name(), |
|
843 resolved_method->signature()), |
|
844 (current_klass.is_null() ? "<NULL>" : current_klass->internal_name())); |
|
845 THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); |
834 } |
846 } |
835 |
847 |
836 if (log_develop_is_enabled(Trace, itables)) { |
848 if (log_develop_is_enabled(Trace, itables)) { |
837 trace_method_resolution("invokeinterface resolved method: caller-class", |
849 trace_method_resolution("invokeinterface resolved method: caller-class", |
838 link_info.current_klass(), resolved_klass, |
850 link_info.current_klass(), resolved_klass, |
982 KlassHandle resolved_klass = link_info.resolved_klass(); |
994 KlassHandle resolved_klass = link_info.resolved_klass(); |
983 methodHandle resolved_method; |
995 methodHandle resolved_method; |
984 if (!resolved_klass->is_interface()) { |
996 if (!resolved_klass->is_interface()) { |
985 resolved_method = resolve_method(link_info, /*require_methodref*/false, CHECK_NULL); |
997 resolved_method = resolve_method(link_info, /*require_methodref*/false, CHECK_NULL); |
986 } else { |
998 } else { |
987 resolved_method = resolve_interface_method(link_info, /*nostatics*/false, CHECK_NULL); |
999 resolved_method = resolve_interface_method(link_info, Bytecodes::_invokestatic, CHECK_NULL); |
988 } |
1000 } |
989 assert(resolved_method->name() != vmSymbols::class_initializer_name(), "should have been checked in verifier"); |
1001 assert(resolved_method->name() != vmSymbols::class_initializer_name(), "should have been checked in verifier"); |
990 |
1002 |
991 // check if static |
1003 // check if static |
992 if (!resolved_method->is_static()) { |
1004 if (!resolved_method->is_static()) { |
1025 methodHandle resolved_method; |
1037 methodHandle resolved_method; |
1026 |
1038 |
1027 if (!resolved_klass->is_interface()) { |
1039 if (!resolved_klass->is_interface()) { |
1028 resolved_method = resolve_method(link_info, /*require_methodref*/false, CHECK_NULL); |
1040 resolved_method = resolve_method(link_info, /*require_methodref*/false, CHECK_NULL); |
1029 } else { |
1041 } else { |
1030 resolved_method = resolve_interface_method(link_info, /*nostatics*/true, CHECK_NULL); |
1042 resolved_method = resolve_interface_method(link_info, Bytecodes::_invokespecial, CHECK_NULL); |
1031 } |
1043 } |
1032 |
1044 |
1033 // check if method name is <init>, that it is found in same klass as static type |
1045 // check if method name is <init>, that it is found in same klass as static type |
1034 if (resolved_method->name() == vmSymbols::object_initializer_name() && |
1046 if (resolved_method->name() == vmSymbols::object_initializer_name() && |
1035 resolved_method->method_holder() != resolved_klass()) { |
1047 resolved_method->method_holder() != resolved_klass()) { |
1300 } |
1312 } |
1301 |
1313 |
1302 methodHandle LinkResolver::linktime_resolve_interface_method(const LinkInfo& link_info, |
1314 methodHandle LinkResolver::linktime_resolve_interface_method(const LinkInfo& link_info, |
1303 TRAPS) { |
1315 TRAPS) { |
1304 // normal interface method resolution |
1316 // normal interface method resolution |
1305 methodHandle resolved_method = resolve_interface_method(link_info, true, CHECK_NULL); |
1317 methodHandle resolved_method = resolve_interface_method(link_info, Bytecodes::_invokeinterface, CHECK_NULL); |
1306 assert(resolved_method->name() != vmSymbols::object_initializer_name(), "should have been checked in verifier"); |
1318 assert(resolved_method->name() != vmSymbols::object_initializer_name(), "should have been checked in verifier"); |
1307 assert(resolved_method->name() != vmSymbols::class_initializer_name (), "should have been checked in verifier"); |
1319 assert(resolved_method->name() != vmSymbols::class_initializer_name (), "should have been checked in verifier"); |
1308 |
1320 |
1309 return resolved_method; |
1321 return resolved_method; |
1310 } |
1322 } |
1317 KlassHandle recv_klass, |
1329 KlassHandle recv_klass, |
1318 bool check_null_and_abstract, TRAPS) { |
1330 bool check_null_and_abstract, TRAPS) { |
1319 // check if receiver exists |
1331 // check if receiver exists |
1320 if (check_null_and_abstract && recv.is_null()) { |
1332 if (check_null_and_abstract && recv.is_null()) { |
1321 THROW(vmSymbols::java_lang_NullPointerException()); |
1333 THROW(vmSymbols::java_lang_NullPointerException()); |
1322 } |
|
1323 |
|
1324 // check if private interface method |
|
1325 if (resolved_klass->is_interface() && resolved_method->is_private()) { |
|
1326 ResourceMark rm(THREAD); |
|
1327 char buf[200]; |
|
1328 jio_snprintf(buf, sizeof(buf), "private interface method requires invokespecial, not invokeinterface: method %s", |
|
1329 Method::name_and_sig_as_C_string(resolved_klass(), |
|
1330 resolved_method->name(), |
|
1331 resolved_method->signature())); |
|
1332 THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); |
|
1333 } |
1334 } |
1334 |
1335 |
1335 // check if receiver klass implements the resolved interface |
1336 // check if receiver klass implements the resolved interface |
1336 if (!recv_klass->is_subtype_of(resolved_klass())) { |
1337 if (!recv_klass->is_subtype_of(resolved_klass())) { |
1337 ResourceMark rm(THREAD); |
1338 ResourceMark rm(THREAD); |